版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。
昨天看一个朋友发的旅游照片,照片处理成了灰度,但是留着蓝色。
突然想到以前的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
紫色 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
但是当代码写好后发现效果不理想,但是颜色又不是线性分布的,所以在这个基础上做了改动:
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,G=0,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, 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
'计算灰度均值,返回灰度颜色
Private Function getAverage(ByVal rgb As Color) As Color
Dim R, G, 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, 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) = "G" Then
pDestColor = pSourceColor
Else
pDestColor = getAverage(pSourceColor)
End If
destImg.SetPixel(i, j, 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, 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) = "B" Then
pDestColor = pSourceColor
Else
pDestColor = getAverage(pSourceColor)
End If
destImg.SetPixel(i, j, 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, 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) = "P" Then
pDestColor = pSourceColor
Else
pDestColor = getAverage(pSourceColor)
End If
destImg.SetPixel(i, j, 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, 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) = "Y" Then
pDestColor = pSourceColor
Else
pDestColor = getAverage(pSourceColor)
End If
destImg.SetPixel(i, j, 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, 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) = "C" Then
pDestColor = pSourceColor
Else
pDestColor = getAverage(pSourceColor)
End If
destImg.SetPixel(i, j, pDestColor)
Next
Next
picDest.Image = destImg
End Sub
由于.net平台下C#和vb.NET很相似,本文也可以为C#爱好者提供参考。
学习更多vb.net知识,请参看vb.net教程目录
————————————————
版权声明:本文为CSDN博主「VB.Net」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。