OpenCvSharp函数:CalcHist直方图和EqualizeHist直方图均衡化

函数说明

函数原型1

void CalcHist(Mat[] images,

int[] channels, InputArray? mask,

OutputArray hist, int dims, int[] histSize,

float[][] ranges, bool uniform = true, bool accumulate = false)

函数原型2

void CalcHist(Mat[] images,

int[] channels, InputArray? mask,

OutputArray hist, int dims, int[] histSize,

Rangef[] ranges, bool uniform = true, bool accumulate = false)

功能说明

计算一个或多个图像的直方图

参数

说明

示例

Mat[] images

一个或多个图像;多个图像的话,深度Depth或大小Size必须相同,类型为 CV_8U、 CV_16U 或 CV_32F

new []{src1,src2}

int[] channels

待计算的通道数组

new []{0,1,2}

InputArray? mask

图像掩膜,可为空,不为空的话必须与images的大小相同的8位数组

null 或 mat

OutputArray hist

输出对应dims维直方图数组

outpputMat

int dims

输出的维数,正整数小于等于CV_MAX_DIMS(当前是32)

1

int[] histSize

每个维度的直方图数组大小(将ranges[i]分为histSize份)

new[] { 256 }

float[][] ranges

每个维度的直方图数组的边界

uniform为true时,只填写一个ranges范围就可以了,对应下限边界(包含)L0和上限边界UhistSize[i]-1;

uniform为false时,

new[] { new Rangef(0, 256) }

实现统计为0到255

bool uniform = true

是否统一(均匀)

true 或 false

bool accumulate = false

累积标志。可累积多个图像的直方图

false 或 true

//直方图均衡化,提高图像对比度
void EqualizeHist(InputArray src, //待均衡化8位单通道图像
                  OutputArray dst)//均衡化后的图像,与输入图像有相同的大小和类型

调用示例

public void Run()
{
    //注意图像路径
    using var src = Cv2.ImRead(ImagePath.LenaColor);
    if (src.Empty()) throw new Exception("图像读取有误");
    Cv2.ImShow("Src", src);

    //统计BGR直方图
    GetHistResult(src, out Mat histBGR, out Mat histBGRImage);

    using var hsvSrc = src.CvtColor(ColorConversionCodes.BGR2HSV);
    //统计HSV直方图
    GetHistResult(hsvSrc, out _, out Mat histHSVImage);

    Cv2.NamedWindow("histBGRImage", WindowFlags.Normal);
    Cv2.ImShow("histBGRImage", histBGRImage);

    Cv2.NamedWindow("histHSVImage", WindowFlags.Normal);
    Cv2.ImShow("histHSVImage", histHSVImage);

    //转为灰度图
    using var srcGray = src.CvtColor(ColorConversionCodes.BGR2GRAY);
    Cv2.ImShow("srcGray", srcGray);
    //直方图均衡化必须为8位单通道
    Cv2.EqualizeHist(srcGray, srcGray);
    //均衡化后的灰度图
    Cv2.ImShow("srcGrayEQ", srcGray);
    //计算均衡化后的直方图
    GetHistResult(srcGray, out _, out Mat histGrayImage);
    Cv2.ImShow("histGrayImage", histGrayImage);

    //分离通道
    var splits = src.Split();
    string[] bgr = new string[] { "Blue", "Green", "Red" };
    Mat[] EqualizeHistMat = new Mat[3];
    int i = 0;
    foreach (var matSplit in splits)
    {
        Cv2.EqualizeHist(matSplit, matSplit);
        GetHistResult(matSplit, out _, out Mat histSplitMat);
        Cv2.ImShow($"EqualizeHist of {bgr[i]}", histSplitMat);
        EqualizeHistMat[i] = matSplit;
        i++;
    }
    using var megreMat = new Mat();
    //合并各通道均衡化的图像
    Cv2.Merge(EqualizeHistMat, megreMat);
    Cv2.ImShow($"Merge BGR EqualizeHist", megreMat);

    Cv2.WaitKey();
    Cv2.DestroyAllWindows();
}

/// <summary>
/// 计算并生成绘制直方图
/// </summary>
/// <param name="src">待统计的图像</param>
/// <param name="hist">直方图结果</param>
/// <param name="histImage">直方图的绘制结果</param>
private void GetHistResult(Mat src, out Mat hist, out Mat histImage)
{

    hist = new Mat();
    const int histW = 512;
    const int histH = 400;
    histImage = new Mat(histH, histW, MatType.CV_8UC3, Scalar.All(0));

    int histSize = 64;//直方图数组大小
    var range = new Rangef(0, 256);//统计0至255(=266-1)
    //将图像像素灰度[0,255]共分为64个等级统计,
    //即值为[0,3]、[4,7]...和[252,255]分别统计,每个范围内的像素个数
    for (int channel = 0; channel < src.Channels(); channel++)
    {
        Cv2.CalcHist(images: new[] { src },//待统计的图像
                    channels: new[] { channel },//待统计的通道
                    mask: null,//掩膜
                    hist: hist,//输出的统计结果
                    dims: 1,//直方图维度
                    histSize: new[] { histSize },//将range分为histSize梯度
                    ranges: new[] { range });//待统计通道像素的范围,不在这个范围内的不统计
        DrawHist(histImage, hist, (channel == 0 ? Scalar.Blue : (channel == 1 ? Scalar.Green : Scalar.Red)));
    }
}

/// <summary>
/// 绘制直方图
/// </summary>
/// <param name="histImage">直方图绘制结果</param>
/// <param name="histSize">直方图数组大小</param>
/// <param name="color">线的颜色</param>
private void DrawHist(Mat histImage, Mat hist, Scalar color)
{
    var binW = Math.Round((double)histImage.Width / hist.Height);
    //归一化
    Cv2.Normalize(hist, hist, 0, histImage.Rows, NormTypes.MinMax, -1);
    for (int i = 1; i < hist.Height; i++)
    {
        var pt1 = new Point2d(binW * (i - 1), histImage.Height - Math.Round(hist.At<float>(i - 1)));
        var pt2 = new Point2d(binW * (i), histImage.Height - Math.Round(hist.At<float>(i)));
        Cv2.Line(histImage, (Point)pt1, (Point)pt2, color, 1, LineTypes.AntiAlias);
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图南科技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值