You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 14:15:05