opencv 绘制直方图 并 重写QLabel 通过鼠标事件得到直方图的值(一)

本文详细介绍了如何使用OpenCV计算并绘制直方图,包括灰度直方图和RGB直方图,并通过重写鼠标事件获取直方图中像素的百分比和值。代码示例中展示了如何使用`calcHist`函数计算直方图,以及用`rectangle`和`line`函数分别绘制填充直方图和轮廓。此外,还提供了绘制直方图的完整过程和最终效果图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

opencv 绘制直方图 并 重写鼠标事件 得到百分比,像素值(一)


提示:以下是本篇文章正文内容,下面案例可供参考

一、opencv直方图计算函数即绘制函数参数解释解析

1、calcHist 直方图计算函数

void calcHist( const Mat* images, int nimages,
                          const int* channels, InputArray mask,
                          SparseMat& hist, int dims,
                          const int* histSize, const float** ranges,
                          bool uniform = true, bool accumulate = false );
参数列表参数功能
1、images你想要获取直方图的原图像
2、nimages输入图像的个数
3、channels获取哪一个通道
4、mask可选的操作掩码
5、hist接收直方图结构
6、dims直方图的通道数
7、histSize直方图的尺寸
8、ranges直方图的范围
9、uniform是否做归一化处理,默认为是
10、accumlate是否累积像素值个数

2、rectangle() 绘制矩形 可以实现填充直方图

void rectangle(CV_IN_OUT Mat& img, Rect rec,
                          const Scalar& color, int thickness = 1,
                          int lineType = LINE_8, int shift = 0);
参数列表参数功能
1、img绘制在那一张图片上
2、rec绘制的矩形大小
3、color绘制的颜色
4、thickness绘制的线条宽度
5、lineType绘制的线型
6、shift坐标的精度,默认为0

3、line() 绘制轮廓 可以实现绘制直方图的轮廓

void line(InputOutputArray img, Point pt1, Point pt2, const Scalar& color,
                     int thickness = 1, int lineType = LINE_8, int shift = 0);
参数列表参数功能
1、img绘制在那一张图片上
2、pt1绘制的起始点
3、平台绘制的结束点
4、color绘制的颜色
5、thickness绘制的线条宽度
6、lineType绘制的线型
7、shift坐标的精度,默认为0

二、功能代码

1、计算并绘制灰度直方图

如果说需要的是直方图的轮廓 而不是填充的那只要把rectangle 函数替换成line 即可

QImage HistogramView::DrawGrayHistogram(QImage image)
{
    cv::Mat gray;
    cv::Mat src = this->QImage2Mat(image);
    cv::cvtColor(src, gray, CV_BGR2GRAY);
    this->m_Flag = GRAY;
    const int channels[] = { 0 };
    int dims = 1;     //设置直方图维度
    const int histSize[] = { 256 }; //直方图每一个维度划分的柱条的数目
    float pranges[] = { 0, 255 };//每个纬度的取值区间
    const float* ranges[] = { pranges };
    cv::calcHist(&gray, 1, channels, cv::Mat(), this->m_Gray_Hist, dims, histSize, ranges, true, false);
    int scale = 2;
    int hist_height = 256;
    cv::Mat hist_img = cv::Mat::zeros(hist_height, 256 * scale, CV_8UC3); //创建一个黑底的8位的3通道图像,高256,宽256*2
    double max_val;
    float total_pix=src.rows*src.cols;
    cv::minMaxLoc(this->m_Gray_Hist, 0, &max_val, 0, 0);//计算直方图的最大像素值
    //将像素的个数整合到 图像的最大范围内
    //遍历直方图得到的数据
    for (int i = 0; i < 256; i++)
    {
        float bin_val = this->m_Gray_Hist.at<float>(i);   //遍历hist元素(注意hist中是float类型)
        int intensity = cvRound(bin_val*hist_height / max_val);  //绘制高度
        cv::rectangle(hist_img, cv::Point(i*scale, hist_height - 1), cv::Point((i + 1)*scale - 1, hist_height - intensity), cv::Scalar(255, 255, 255));//绘制直方图
    }
    /*绘制轮廓
    for (int i = 0; i < 255; i++)
    {
        float bin_val = this->m_Gray_Hist.at<float>(i);   //遍历hist元素(注意hist中是float类型)
        float bin_val2 = this->m_Gray_Hist.at<float>(i+1); //后一个像素值
        int intensity = cvRound(bin_val*hist_height / max_val);  //绘制高度
        int intensity2 = cvRound(bin_val2*hist_height / max_val);
        cv::line(hist_img, cv::Point(i*scale,hist_height - intensity), cv::Point((i + 1)*scale - 1,hist_height - intensity2), cv::Scalar(255, 255, 255));
    }
    */
    this->m_totalpixeldata->setText(QString("%1").arg(total_pix));
    return this->Mat2QImage(hist_img);
}

2、计算并绘制RGB 直方图

QImage HistogramView::DrawBGRHistogram(QImage image, int flag)
{
    if(image.isNull())
        return image;
    cv::Mat src = this->QImage2Mat(image);
    std::vector<cv::Mat> bgr_planes;
    int dims = 1;
    const int histSize[] = { 256 };
    float pranges[] = { 0, 255 };
    const float* ranges[] = { pranges };
    cv::split(src, bgr_planes);
    int scale = 2;
    int hist_height = 256;
    cv::Mat hist_img = cv::Mat::zeros(hist_height, 256 * scale, CV_8UC3); //创建一个黑底的8位的3通道图像,高256,宽256*2
    double max_val;
    float total_pix=src.rows*src.cols;
    switch(flag)
    {
    case BLUE:
        this->m_Flag = BLUE;
        cv::calcHist(&bgr_planes[0], 1,0,cv::Mat(),this->m_Blue_Hist,dims, histSize, ranges, true, false);  //计算直方图
        cv::minMaxLoc(m_Blue_Hist,0,&max_val,0,0);
        for (int i = 0; i < 256; i++)
        {
            float bin_val = m_Blue_Hist.at<float>(i);   //遍历hist元素(注意hist中是float类型)
            int intensity = cvRound(bin_val*hist_height / max_val);  //绘制高度
            cv::rectangle(hist_img, cv::Point(i*scale, hist_height - 1), cv::Point((i + 1)*scale - 1, hist_height - intensity), cv::Scalar(255, 255, 255));//绘制直方图
        }
        break;
    case GREEN:
        this->m_Flag = GREEN;
        cv::calcHist(&bgr_planes[1], 1,0,cv::Mat(),this->m_Green_Hist,dims, histSize, ranges, true, false);
        cv::minMaxLoc(this->m_Green_Hist,0,&max_val,0,0);
        for (int i = 0; i < 256; i++)
        {
            float bin_val = this->m_Green_Hist.at<float>(i);   //遍历hist元素(注意hist中是float类型)
            int intensity = cvRound(bin_val*hist_height / max_val);  //绘制高度
            cv::rectangle(hist_img, cv::Point(i*scale, hist_height - 1), cv::Point((i + 1)*scale - 1, hist_height - intensity), cv::Scalar(255, 255, 255));//绘制直方图
        }
        break;
    case RED:
        this->m_Flag = RED;
        cv::calcHist(&bgr_planes[2], 1,0,cv::Mat(),this->m_Red_Hist,dims, histSize, ranges, true, false);
        cv::minMaxLoc(this->m_Red_Hist,0,&max_val,0,0);
        for (int i = 0; i < 256; i++)
        {
            float bin_val = this->m_Red_Hist.at<float>(i);   //遍历hist元素(注意hist中是float类型)
            int intensity = cvRound(bin_val*hist_height / max_val);  //绘制高度
            cv::rectangle(hist_img, cv::Point(i*scale, hist_height - 1), cv::Point((i + 1)*scale - 1, hist_height - intensity), cv::Scalar(255, 255, 255));//绘制直方图
        }
        break;
    }
    this->m_totalpixeldata->setText(QString("%1").arg(total_pix));
    return this->Mat2QImage(hist_img);

}

三、效果图

1、原图

在这里插入图片描述

2、灰度直方图

填充效果

在这里插入图片描述

轮廓效果

在这里插入图片描述

2、RGB 直方图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

BigProgrambug

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

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

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

打赏作者

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

抵扣说明:

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

余额充值