昨天看一个朋友发的旅游照片,照片处理成了灰度,但是留着蓝色。
突然想到以前的Lumia830手机上也有这样一款软件可以处理颜色,只留下红色、绿色或者蓝色这样的单一颜色。
在写这个代码之前,我先考虑了主要颜色的算法,所以有了初始设定:
红色 R>128 R-G>100 & R-B>100
绿色 G>128 G-R>100 & G-B>100
蓝色 B>128 B-R>100 & B-G>100
绿色 G>128 G-R>100 & G-B>100
蓝色 B>128 B-R>100 & B-G>100
紫色 R>128 B>128 B>=R R-G>128 B-R>128
黄色 R>190 G>190 R>=G R-B>128 G-B>128
普蓝 G>190 B>190 B>=G B-R>128 G-R>128
黄色 R>190 G>190 R>=G R-B>128 G-B>128
普蓝 G>190 B>190 B>=G B-R>128 G-R>128
Private Function getSingleColor(ByVal rgb As Color) As String Dim R,G,B As Integer R = rgb.R G = rgb.G B = rgb.B If (R > 128) AndAlso (R - G > 30) AndAlso (R - B > 30) Then Return "R" If (G > 80) AndAlso (G - R > 5) AndAlso ((G - B > 20) Or (B - G) < 10) Then Return "G" If (B > 80) AndAlso (B - R > 50) AndAlso (B - G > 30) Then Return "B" If (R > 128) AndAlso (B > 128) AndAlso (R - G > 30) AndAlso (B - G > 30) Then Return "P" If (R > 140) AndAlso (G > 120) AndAlso (Math.Abs(G - R) < 40) AndAlso (R - B > 80) AndAlso (G - B > 80) Then Return "Y" If (G > 180) AndAlso (B > 180) AndAlso ((B >= G) Or (G - B) < 10) AndAlso (B - R > 40) AndAlso (G - R > 40) Then Return "C" Return "N" End Function
上述代码过程中,按照颜色划分了6个色系,分别是 红R、绿G、蓝B、紫P、黄Y、普蓝C(我这边是这么称呼的,也又叫做天蓝色),其他N(也就是需要处理为灰度的颜色)。
说明一下,
以下是个人一些不成熟的想法:
1、红绿蓝不说了,三原色;紫色对应的是(R=255;G=0;B=255)、黄色对应的是(R=255;G=255;B=0);普蓝色对应的是(R=0;G=255;B=255),然后就是白色(R=255;G=255;B=255)、黑色(R=0;G=0;B=0)以及灰色(按照均值计算,请参看《
vb.net 教程 5-13 图像处理之像素处理 3》)
2、开始想的是只按照绝对的RGB颜色值来划分,例如单纯的取红色(R=255,G=0,B=0),那么和红色接近的颜色(R=236,B=0)人眼看到的也算是红色的。是不是也应该算?
3、颜色其实也是三原色交错分布的,如果单纯的将R、G、B值记录到数据库来作为划分的依据,工作量比较大。
4、尽量使用简单的方法来做。
以下是处理“红色”比较完整的代码:
'红色按钮 Private Sub Button1_Click(sender As Object,e As EventArgs) Handles Button1.Click Dim pSourceColor As Color Dim pDestColor As Color Dim destImg As New Bitmap(sourceImg.Width,sourceImg.Height) For i As Integer = 0 To sourceImg.Width - 1 For j As Integer = 0 To sourceImg.Height - 1 pSourceColor = sourceImg.GetPixel(i,j) If getSingleColor(pSourceColor) = "R" Then pDestColor = pSourceColor Else pDestColor = getAverage(pSourceColor) End If destImg.SetPixel(i,j,pDestColor) Next Next picDest.Image = destImg End Sub '计算所属色系,并返回色系缩写字母 Private Function getSingleColor(ByVal rgb As Color) As String Dim R,B As Integer R = rgb.R G = rgb.G B = rgb.B If (R > 128) AndAlso (R - G > 30) AndAlso (R - B > 30) Then Return "R" If (G > 80) AndAlso (G - R > 5) AndAlso ((G - B > 20) Or (B - G) < 10) Then Return "G" If (B > 80) AndAlso (B - R > 50) AndAlso (B - G > 30) Then Return "B" If (R > 128) AndAlso (B > 128) AndAlso (R - G > 30) AndAlso (B - G > 30) Then Return "P" If (R > 140) AndAlso (G > 120) AndAlso (Math.Abs(G - R) < 40) AndAlso (R - B > 80) AndAlso (G - B > 80) Then Return "Y" If (G > 180) AndAlso (B > 180) AndAlso ((B >= G) Or (G - B) < 10) AndAlso (B - R > 40) AndAlso (G - R > 40) Then Return "C" Return "N" End Function '计算灰度均值,返回灰度颜色 Private Function getAverage(ByVal rgb As Color) As Color Dim R,B As Integer Dim gray As Integer R = rgb.R G = rgb.G B = rgb.B gray = (R + G + B) / 3 Dim newColor As Color newColor = Color.FromArgb(gray,gray,gray) Return newColor End Function
Dim sourceImg As Bitmap
‘载入图片 Private Sub btnLoadimg_Click(sender As Object,e As EventArgs) Handles btnLoadimg.Click Dim filename As String If OpenFileDialog1.ShowDialog = DialogResult.OK Then filename = OpenFileDialog1.FileName Else Exit Sub End If sourceImg = Image.FromFile(filename) picSource.Image = sourceImg End Sub
其他几种颜色的代码:
'绿色 Private Sub Button2_Click(sender As Object,e As EventArgs) Handles Button2.Click Dim pSourceColor As Color Dim pDestColor As Color Dim destImg As New Bitmap(sourceImg.Width,j) If getSingleColor(pSourceColor) = "G" Then pDestColor = pSourceColor Else pDestColor = getAverage(pSourceColor) End If destImg.SetPixel(i,pDestColor) Next Next picDest.Image = destImg End Sub '蓝色 Private Sub Button3_Click(sender As Object,e As EventArgs) Handles Button3.Click Dim pSourceColor As Color Dim pDestColor As Color Dim destImg As New Bitmap(sourceImg.Width,j) If getSingleColor(pSourceColor) = "B" Then pDestColor = pSourceColor Else pDestColor = getAverage(pSourceColor) End If destImg.SetPixel(i,pDestColor) Next Next picDest.Image = destImg End Sub '紫色 Private Sub Button4_Click(sender As Object,e As EventArgs) Handles Button4.Click Dim pSourceColor As Color Dim pDestColor As Color Dim destImg As New Bitmap(sourceImg.Width,j) If getSingleColor(pSourceColor) = "P" Then pDestColor = pSourceColor Else pDestColor = getAverage(pSourceColor) End If destImg.SetPixel(i,pDestColor) Next Next picDest.Image = destImg End Sub '黄色 Private Sub Button5_Click(sender As Object,e As EventArgs) Handles Button5.Click Dim pSourceColor As Color Dim pDestColor As Color Dim destImg As New Bitmap(sourceImg.Width,j) If getSingleColor(pSourceColor) = "Y" Then pDestColor = pSourceColor Else pDestColor = getAverage(pSourceColor) End If destImg.SetPixel(i,pDestColor) Next Next picDest.Image = destImg End Sub '普蓝色 Private Sub Button6_Click(sender As Object,e As EventArgs) Handles Button6.Click Dim pSourceColor As Color Dim pDestColor As Color Dim destImg As New Bitmap(sourceImg.Width,j) If getSingleColor(pSourceColor) = "C" Then pDestColor = pSourceColor Else pDestColor = getAverage(pSourceColor) End If destImg.SetPixel(i,pDestColor) Next Next picDest.Image = destImg End Sub
由于.net平台下C#和vb.NET很相似,本文也可以为C#爱好者提供参考。
学习更多vb.net知识,请参看 vb.net 教程 目录