我正在尝试编写一个解决方案,以便我的用户可以用他们的公司徽标"水印"他们的图像。我已经完成了实际的水印部分,现在我正在创建"上传徽标"功能,这样他们就可以为我提供他们希望在图像上添加水印的徽标。
我使用的是VB.NET,这可能最终会出现在一个Web服务中,该服务接受Logo JPG文件,并返回"已更改"的Logo。在这个Web服务中,我需要做的是:
1) 对图像进行灰度处理。感谢这篇文章,我也一直在工作。
2) 使背景透明(使徽标在图像上加水印时看起来干净)。这就是我被卡住的地方。
我认为大多数情况下,上传的任何徽标都会有一个通用的白色背景,但我不能这么认为。有没有一种方法可以以某种方式检测图像的背景或的背景颜色,这样我就可以使这些颜色 我已经从code.google.com下载并运行了这个名为Transpoint的项目,这正是我所需要的,只是我无法将其作为一个独立的应用程序。此外,我认为这是用Python编写的,这对我来说是陌生的 所以基本上,我需要的只是一种确定图像背景的方法(如果可能的话?),甚至只是背景颜色,这样我就可以使它们透明。如有任何帮助/建议,我们将不胜感激! 谢谢,Lloyd
您可以读取左上角的像素,并假设该像素代表背景颜色,然后在图像中迭代,并将每个匹配像素的alpha值(按颜色匹配)设置为0。
然而,我可以向你保证,结果会很糟糕。为了使透明度正常工作并看起来良好,图像需要支持部分透明度,这样一些像素是完全透明的,而一些像素只是部分透明的。任何采用不透明图像并仅将图像中的一种颜色设置为完全透明的算法最终都会出现锯齿状边缘。
我接触过的大多数公司的标志都是由专业艺术家制作的,具有平滑、部分透明的效果。你最好只要求客户提交一个透明的标志,而不是试图用代码将不透明的图像变成透明的。抱歉,但这根本不起作用。
我认为这实际上会起作用(对不起,这只是一个描述):
假设左上角像素是图像的背景色,则可以遍历图像中的每个像素,如果像素颜色与背景色匹配(完全匹配或在某个阈值颜色距离内),则可以将alpha设置为0。当你在不同颜色的背景上重新绘制时,这会给你留下一个透明背景但边缘锯齿状的图像。此外,如果背景颜色出现在图像本身内部的任何位置,它将变为透明,这是您不希望的。
为了解决后一个问题,你的算法应该从左到右开始扫描图像的每一行,当它到达非背景色像素时停止;此时,它应该从同一行开始,从右向左扫描,直到到达非bg像素。
若要修复边,可以只模糊位图的alpha值。基本上,您将每个像素的alpha值重新计算为9个像素的平均值(其本身及其周围的8个像素,仅alpha值,而不是rgb值)。为了防止排序伪影,您将使用一个临时数组来存储平均像素值,然后在处理结束时将其复制回图像的alpha值。
此外,可能有一个或多个第三方工具可以做到这一点(LEAD工具还在吗?)。
@MusiGenesis(以及其他可能感兴趣的人)以下是我为(某种程度上)解决我的问题所做的。我基本上遵循了你想法的前半部分。我创建了一个函数,它将接受bitmap
,将每个像素与(0,0)处的第一个像素进行检查,每个RGB颜色使用10的阈值。对于该阈值内的每种颜色,像素都是透明的。这是我的代码,它似乎适用于我尝试过的少数图像:
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