Программно определить фон изображения (логотипы и т. Д.) И сделать прозрачным? - PullRequest
1 голос
/ 21 мая 2011

Я пытаюсь написать решение, чтобы мой пользователь мог "ставить водяные знаки" на своих изображениях с помощью логотипа своей компании. Я уже сделал и работаю с водяными знаками, так что теперь я создаю функцию «загрузить логотип», чтобы они могли предоставить мне логотип, который они хотят сделать водяным знаком на своих изображениях.

Я использую VB.NET, и это, вероятно, закончится веб-службой, которая принимает файл логотипа JPG и возвращает «измененный» логотип. В этом веб-сервисе мне нужно:

1) Серая шкала изображения. Который у меня тоже работает, благодаря этой статье .

2) Сделайте фон прозрачным (чтобы логотип выглядел чистым, если на него нанесен водяной знак). Вот где я застрял.

Я думаю, что по большей части любые загруженные логотипы будут иметь общий белый фон, но я не могу этого допустить. Есть ли способ как-то обнаружить фон изображения или цвета фона , чтобы я мог сделать эти цвета прозрачными?

Я скачал и запустил этот проект с code.google.com , который называется Transpoint, и это почти то, что мне нужно, за исключением того, что я не смогу использовать его как отдельное приложение , Кроме того, я думаю, что это написано на Python, что мне чуждо.

Так что в основном мне нужен только способ определения фона на изображении (если это вообще возможно?) Или даже просто цвета фона, чтобы я мог сделать их прозрачными. Любая помощь / совет / предложения будут с благодарностью!

Спасибо, Lloyd

Ответы [ 3 ]

3 голосов
/ 21 мая 2011

Вы могли бы сделать что-то вроде чтения верхнего левого пикселя и предположения, что этот пиксель представляет цвет фона, а затем итерации по изображению и установки значения альфа каждого соответствующего пикселя (сопоставления по цвету) равным 0.

Я могу в значительной степени гарантировать вам, однако, что результат будет ужасным. Чтобы прозрачность работала правильно и выглядела хорошо, изображение должно поддерживать частичную прозрачность, чтобы некоторые пиксели были полностью прозрачными, а некоторые - только частично прозрачными. Любой алгоритм, который берет непрозрачное изображение и устанавливает только один цвет в изображении для полной прозрачности, в конечном итоге будет иметь неровные края.

Большинство компаний, с которыми я когда-либо имел дело, имеют версии своих логотипов, сделанные профессиональными художниками, с гладкой, частичной прозрачностью. Вам было бы гораздо лучше просто потребовать от клиентов предоставить логотип с прозрачностью, чем пытаться превратить непрозрачное изображение в прозрачное с кодом. Извините, но это просто не работает.

1 голос
/ 24 мая 2011

@ MusiGenesis (и все, кому это может быть интересно), вот что я сделал, чтобы (вроде) решить мою проблему.Я в основном следовал первой половине вашей идеи.Я создал функцию, которая будет принимать bitmap, проверять каждый пиксель по отношению к первому пикселю в (0,0) - используя порог 10 для каждого цвета RGB.Для каждого цвета в этом пороге пиксель становится прозрачным.Вот мой код, который, кажется, работает хорошо для тех нескольких изображений, с которыми я пробовал:

Private Function TransparifyBackground(ByVal bmp As Bitmap) As Bitmap

        Dim temp As Color

        Dim background As Color = bmp.GetPixel(0, 0) 'top left will be assumed background color

        For y As Integer = 0 To bmp.Height - 1
            For x As Integer = 0 To bmp.Width - 1

                'get the pixel for this position:
                temp = bmp.GetPixel(x, y)

                If ColorsMatch(background, temp) Then

                    'Make the Alpha value 50 for each pixel, leaving the other colors
                    Dim newColor As New Color
                    newColor = Color.Transparent

                    bmp.SetPixel(x, y, newColor)

                End If

            Next
        Next

        Return bmp

    End Function

    Private Function ColorsMatch(ByVal background As Color, ByVal temp As Color) As Boolean

        Dim nThreshold As Integer = 10

        Dim temp_R As Integer = CInt(temp.R)
        Dim temp_G As Integer = CInt(temp.G)
        Dim temp_B As Integer = CInt(temp.B)

        Dim R As Integer = CInt(background.R)
        Dim G As Integer = CInt(background.G)
        Dim B As Integer = CInt(background.B)

        'check the difference of each value against our threshold:
        If ((temp_R - R) < nThreshold) AndAlso ((temp_G - G) < nThreshold) AndAlso ((temp_B < B) < nThreshold) Then
            Return True
        Else
            Return False
        End If

    End Function
1 голос
/ 21 мая 2011

Я думаю, что это действительно сработает (извините, это просто описание):

Предполагая, что верхний левый угловой пиксель является цветом фона изображения, вы можете перебирать каждый пиксель изображения и устанавливать альфа в 0, если цвет пикселя соответствует цвету фона (либо точно, либо в пределах некоторого порогового цветового расстояния). После этого у вас останется изображение с прозрачным фоном, но с зазубренными краями, когда вы перерисовываете его на фоне другого цвета. Кроме того, если цвет фона присутствует где-либо внутри самого изображения, оно станет прозрачным, что вам не нужно.

Чтобы решить последнюю проблему, ваш алгоритм должен начать сканирование каждой строки изображения слева направо и прекратить работу, когда он достигнет пикселя без фона; в этот момент он должен начинаться в той же строке и сканироваться справа налево, пока не достигнет пикселя не bg.

Чтобы исправить края, вы можете просто размыть альфа-значения растрового изображения. По сути, вы заново вычисляете альфа-значение каждого пикселя как среднее значение для 9 пикселей (самого себя и 8 пикселей, окружающих его, и просто альфа-значений, а не значений rgb). Чтобы предотвратить появление артефактов секвенирования, у вас будет временный массив для хранения усредненных значений пикселей, который вы затем скопируете обратно в альфа-значения изображения в конце процесса.

Также, возможно, есть один или несколько сторонних инструментов, которые делают это (LEAD Tools все еще есть?).

...