C#实现图像红色通道滤镜:非红色像素置黑的技术问题
红色通道滤镜(Red Pass Filter)实现问题
我正在用C#编写红色通道滤镜,目标是将所有非红色像素转换为黑色(0,0,0),逻辑类似高通滤镜将阈值以下的频率置为0。但实际使用相机拍摄的图像时遇到了问题:红色像素并非标准的(255,0,0),且受拍摄物体的光影影响,同一物体上的红色像素存在明暗差异。
我已经尝试了三种红色像素判断方法:
// 判断像素是否为红色系:红色分量大于绿色和蓝色分量 public bool IsRed(RGB color) { return color.Red > color.Green && color.Red > color.Blue; } // 判断像素是否为红色系:红色分量在128-255范围内 public bool IsRed2(RGB color) { return color.Red >= 128 && color.Red <= 255; } // 判断像素是否为红色系:通过HSL色彩空间的色相范围判断 public bool IsRed3(RGB color) { double hue, saturation, lightness; RGBToHSL(color.Red, color.Green, color.Blue, out hue, out saturation, out lightness); // 色相在0-30度或330-360度范围内则属于红色系 return (hue >= 0 && hue <= 30) || (hue >= 330 && hue <= 360); } // 将RGB值转换为HSL色彩空间 private void RGBToHSL(byte red, byte green, byte blue, out double hue, out double saturation, out double lightness) { // 将RGB值转换为0-1范围的浮点数 double r = red / 255.0; double g = green / 255.0; double b = blue / 255.0; // 计算RGB分量的最大值和最小值 double max = Math.Max(r, Math.Max(g, b)); double min = Math.Min(r, Math.Min(g, b)); // 计算亮度(Lightness) lightness = (max + min) / 2; // 计算饱和度(Saturation) if (max == min) { // 灰度色彩,色相为0,饱和度为0 hue = 0; saturation = 0; } else { // 非灰度色彩 double d = max - min; saturation = lightness > 0.5 ? d / (2 - max - min) : d / (max + min); // 计算色相(Hue) if (max == r) { hue = (g - b) / d + (g < b ? 6 : 0); } else if (max == g) { hue = (b - r) / d + 2; } else { hue = (r - g) / d + 4; } hue /= 6; } }
更新补充:图像RGB值提取实现代码
private RGB[,] ImageToRGBByteArray(Bitmap _image, int height, int width) { Bitmap b = new Bitmap(_image); BitmapData bData = b.LockBits(new Rectangle(0, 0, _image.Width, _image.Height), ImageLockMode.ReadWrite, b.PixelFormat); /* GetBitsPerPixel方法根据PixelFormat返回对应的位深度 */ BitsPerPixel = GetBitsPerPixel(bData.PixelFormat); /* 图像的总字节大小 */ int size = bData.Stride * bData.Height; Stride = bData.Stride; /* 为图像数据分配缓冲区 */ byte[] data = new byte[size]; RGB[,] imagematrix = new RGB[height, width]; int[,] imageData = new int[height, width]; /* 将图像数据从Scan0复制到data缓冲区 */ Marshal.Copy(bData.Scan0, data, 0, size); int i = 0; ModifiedHistogram = null; ImageData = null; ImageRGBData = null; Dictionary<RGB, int> modifiedHistogram = new Dictionary<RGB, int>(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { RGB tempValue = new RGB(data[i], data[i + 1], data[i + 2]); imagematrix[y, x] = tempValue; imageData[y, x] = (int)((data[i] + data[i + 1] + data[i + 2]) / 3D); if (!modifiedHistogram.ContainsKey(tempValue)) modifiedHistogram.Add(tempValue, 1); else modifiedHistogram[tempValue]++; i += BitsPerPixel / 8; } } int maxValue = 0; string color = string.Empty; foreach (var kvp in modifiedHistogram) { if (kvp.Value > maxValue) { maxValue = kvp.Value; color = kvp.Key.ColorName; } } ImageData = imageData; ImageRGBData = imagematrix; ModifiedHistogram = modifiedHistogram; return imagematrix; }
数据分量说明:
data[i] = 红色分量 data[i+2] = 绿色分量 data[i+3] = 蓝色分量
RGB类定义
public class RGB { public byte Red { get; set; } public byte Green { get; set; } public byte Blue { get; set; } public RGB(byte red, byte green, byte blue) { Red = red; Green = green; Blue = blue; SetColorName(); } public override bool Equals(object obj) { RGB other = obj as RGB; return other != null && other.ColorName == this.ColorName; } }
内容的提问来源于stack exchange,提问作者Brandon
相关产品推荐
相关产品推荐

