OpenCV C++图像色彩匹配代码转EmguCV C#版本问题求解
问题解决方法
1. Mat元素访问、赋值与比较
EmguCV不支持C++中mat(p)的调用语法,需通过泛型索引器访问元素:
- 单通道8位无符号类型(DepthType.Cv8U)使用
GetGenericIndexer<byte>()获取索引器 - 单通道64位浮点类型(DepthType.Cv64F)使用
GetGenericIndexer<double>()获取索引器 - 一维索引p可转换为坐标
y = p / img.Cols; x = p % img.Cols,即可通过索引器读写对应位置的值,数值比较逻辑直接使用取出的值判断即可
2. 通道集合与Split方法调用
CvInvoke.Split不支持List<Mat>类型参数,需声明为Mat[]数组类型,同时天然支持[]索引访问单个通道,符合后续操作要求
修正后完整可运行代码
using Emgu.CV; using Emgu.CV.CvEnum; using Emgu.CV.Structure; using System; public static class EmguCVColourMatchingHelper { // Compute histogram and CDF for an image with mask public static void do1ChnHist(Mat img, Mat mask, Mat h, Mat cdf) { var imgIndexer = img.GetGenericIndexer<byte>(); var maskIndexer = mask.GetGenericIndexer<byte>(); var hIndexer = h.GetGenericIndexer<double>(); var cdfIndexer = cdf.GetGenericIndexer<double>(); for (var p = 0; p < (int)img.Total; p++) { int y = p / img.Cols; int x = p % img.Cols; if (maskIndexer[y, x] > 0) { byte c = imgIndexer[y, x]; hIndexer[0, c] += 1.0; } } CvInvoke.Normalize(h, h, 1, 0, NormType.MinMax); cdfIndexer[0, 0] = hIndexer[0, 0]; for (int j = 1; j < 256; j++) { cdfIndexer[0, j] = cdfIndexer[0, j - 1] + hIndexer[0, j]; } CvInvoke.Normalize(cdf, cdf, 1, 0, NormType.MinMax); } public static void histMatchRGB(Mat src, Mat src_mask, Mat dst, Mat dst_mask) { double histmatch_epsilon = 0.000001; Mat[] chns = new Mat[3]; Mat[] chns1 = new Mat[3]; CvInvoke.Split(src, chns); CvInvoke.Split(dst, chns1); for (int i = 0; i < 3; i++) { Mat src_hist = new Mat(1, 256, DepthType.Cv64F, 1); src_hist.SetTo(new Scalar(0)); Mat dst_hist = new Mat(1, 256, DepthType.Cv64F, 1); dst_hist.SetTo(new Scalar(0)); Mat src_cdf = new Mat(1, 256, DepthType.Cv64F, 1); src_cdf.SetTo(new Scalar(0)); Mat dst_cdf = new Mat(1, 256, DepthType.Cv64F, 1); dst_cdf.SetTo(new Scalar(0)); do1ChnHist(chns[i], src_mask, src_hist, src_cdf); do1ChnHist(chns1[i], dst_mask, dst_hist, dst_cdf); byte last = 0; Mat lut = new Mat(1, 256, DepthType.Cv8U, 1); var srcCdfIndexer = src_cdf.GetGenericIndexer<double>(); var dstCdfIndexer = dst_cdf.GetGenericIndexer<double>(); var lutIndexer = lut.GetGenericIndexer<byte>(); for (int j = 0; j < src_cdf.Cols; j++) { double F1j = srcCdfIndexer[0, j]; for (byte k = last; k < dst_cdf.Cols; k++) { double F2k = dstCdfIndexer[0, k]; if (Math.Abs(F2k - F1j) < histmatch_epsilon || F2k > F1j) { lutIndexer[0, j] = k; last = k; break; } } } CvInvoke.LUT(chns[i], lut, chns[i]); } Mat res = new Mat(); CvInvoke.Merge(chns, res); res.CopyTo(src); } internal static void Main(string[] args) { Mat src = CvInvoke.Imread("e:/test/iO6S1m.png"); Mat dst = CvInvoke.Imread("e:/test/kfku3m.png"); Mat mask = new Mat(src.Size, DepthType.Cv8U, 1, new Scalar(255)); histMatchRGB(dst, mask, src, mask); CvInvoke.Imwrite("e:/test/result.png", dst); } }
内容的提问来源于stack exchange,提问作者Oliver Spencer
相关产品推荐
相关产品推荐

