opencv学习20-23——折线直方图,柱状直方图,归一化,均衡化

定义

直方图是数学中的一种表达工具,在统计学中应用颇多,直方图是一个二维的图标,如果放在坐标系中就是横轴和纵轴,分别表示不同的参数,在图像中就是图像样本的整体与图像单个的属性之间的统计关系。通俗的理解就是在横轴参数的不同区间内,某一特征或属性的数量或频率是多少。分类有灰度直方图,图像直方图,还有归一化和均衡化以及利用直方图的相关应用。

直方图的绘制

OpenCV提供了相关的API,如下所示。OpenCV提供了两个重载的calcHist函数,它可以计算一系列阵列的直方图,这些系列通常是图像或像平面。它最多可以同时处理32个维度。

C++: void calcHist(
    const Mat* images, //要处理的图像,类型为CV_8U或 CV_32F
    int nimages, //要处理图像的数量
    const int* channels, //图像的通道序列
    InputArray mask, //可自定义,与image尺寸相同的矩阵,默认Mat()输出的直方图
    OutputArray hist, //输出直方图
    int dims, //输出直方图的维度,最大为32 
    const int* histSize, //数组,存储不同维度的取样数量
    const float** ranges, //二维数组与uniform和accumulate有关
    bool uniform=true, //默认true,是否归一化
    bool accumulate = false //默认false)
//下面同上,区别在于参数定义类型
C++: 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 )

完整代码如下

#include<opencv2/opencv.hpp>
#include"iostream"
using namespace cv;
void main()
{
	Mat dst, dst1;
	Mat img = imread("ck567.jpg");
	if (!img.data)
	{
		printf("fail to load jpg!\n");
	}
	else
	{
		imshow("original image", img);
		//通道分离
		vector<Mat>bgr_channel;
		split(img,bgr_channel);
		//计算直方图
		int histsize = 256;//0~255共256个灰度级
		float range[] = { 0,256 };//区间范围
		const float*histRanges = { range };
		Mat b_hist, g_hist, r_hist;
		calcHist(&bgr_channel[0], 1, 0, Mat(), b_hist, 1, &histsize, &histRanges, true, false);
		calcHist(&bgr_channel[1], 1, 0, Mat(), g_hist, 1, &histsize, &histRanges, true, false);
		calcHist(&bgr_channel[2], 1, 0, Mat(), r_hist, 1, &histsize, &histRanges, true, false);
		//归一化
		int hist_h = 325;//直方图的图像的行数
		int hist_w = 580;//直方图的图像的列数
		double bin_w = hist_w / histsize;//每一个灰度级区间的宽度
		Mat histImage(hist_h, hist_w, CV_8UC3, Scalar(0, 0, 0));//绘制直方图显示的图像
		normalize(b_hist, b_hist, 0, hist_h*0.8, NORM_MINMAX, -1, Mat());//归一化
		normalize(g_hist, g_hist, 0, hist_h*0.8, NORM_MINMAX, -1, Mat());
		normalize(r_hist, r_hist, 0, hist_h*0.8, NORM_MINMAX, -1, Mat());
		//绘制直方图
		for (int i = 1; i < histsize; i++)
		{
			//绘制蓝色分量直方图
			line(histImage, Point((i - 1)*bin_w, hist_h - cvRound(b_hist.at<float>(i - 1))),
				Point((i)*bin_w, hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, CV_AA);
			//绘制绿色分量直方图
			line(histImage, Point((i - 1)*bin_w, hist_h - cvRound(g_hist.at<float>(i - 1))),
				Point((i)*bin_w, hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, CV_AA);
			//绘制红色分量直方图
			line(histImage, Point((i - 1)*bin_w, hist_h - cvRound(r_hist.at<float>(i - 1))),
				Point((i)*bin_w, hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, CV_AA);
		}
		imshow("histogram iamge", histImage);
		waitKey(0);
		destroyAllWindows();
	}
}

效果如下

上面是直方图的简单绘制,只能够粗略的看出某一范围内的RGB多少,并没有提供数据价值,因此如果能够在坐标系中显示直方图,并配有坐标,也是一大改进。

代码如下

#include"opencv2/core/core.hpp"
#include"opencv2/highgui/highgui.hpp"
#include<opencv2/opencv.hpp>
#include "math.h"
#include"iostream"
using namespace cv;

void main()
{
	int histSize = 50;
	Mat img = imread("ck567.jpg",0);
	imshow( "orignal jpg",img);
	Mat hist;//计算得到的直方图结果
	char string[10];
        float ranges[2] = {0,256};
        const float *histRanges[1] = {ranges}; 
        Mat histimg(512,256*4,CV_8UC3,Scalar(0,0,0));

        //计算图像的直方图
        calcHist(&img,1,0,Mat(),hist,1,&histSize,histRanges,true,false);
        double maxVal = 0;
        Point maxLoc;
        minMaxLoc(hist, NULL, &maxVal, NULL, &maxLoc);//寻找最大值及其位置
        double bin_w =(double) histimg.cols / histSize;  // histSize: 条的个数,则 bin_w 为条的宽度
        double bin_h = (double)histimg.rows/ maxVal;  // maxVal: 最高条的像素个数,则 bin_u 为单个像素的高度
        // 画直方图
        for(int i=0;i<histSize;i++)
        {
            Point p0=Point(i*bin_w,histimg.rows);
            float binValue = hist.at<float>(i);        
            Point p1=Point((i+1)*bin_w,histimg.rows-binValue*bin_h);
            rectangle(histimg,p0,p1,Scalar(255,0,0),2,8,0);
        }
        //画纵坐标刻度(像素个数)
        int k=0;
        for(int i=1;k<maxVal;i++)
        {
            k=i*maxVal/10;
            sprintf(string,"%d",k);
            putText(histimg, string , Point(0,histimg.rows-k*bin_h),FONT_HERSHEY_SIMPLEX,0.5,Scalar(255,255,0),1);
            line( histimg,Point(0,histimg.rows-k*bin_h),Point(histimg.cols-1,histimg.rows-k*bin_h),Scalar(0,255,0));
        }
        //画横坐标刻度(像素灰度值)
        k=0;
        for(int i=1;k<256;i++)
        {
            k=i*30;
            sprintf(string,"%d",k);
            putText(histimg, string , Point(k*(histimg.cols / 256),histimg.rows), FONT_HERSHEY_SIMPLEX,0.5,Scalar(255,255,0),1);
        }
        imshow( "Hist", histimg );
	waitKey(0);
	destroyAllWindows();
}

效果如下

以上是直方图的绘制,重点如何在图像上进行定标画图。

直方图均衡化

直方图均衡化是直方图在图像处理中的一个应用。用于提高对比度,增强细节,便于观察。OpenCV提供的API如下所示。

C++ void equalizeHist(InputArray src, OutputArray dst)

灰度图均衡化代码如下

#include<opencv2/opencv.hpp>
#include "math.h"
#include"iostream"
using namespace cv;
void main()
{
	Mat img = imread("1.jpg",0);
	imshow("orignal jpg",img);
	equalizeHist(img,img);
        imshow("Hist",img);
	waitKey(0);
	destroyAllWindows();
}

效果如下

彩色图均衡化代码如下

#include"opencv2/core/core.hpp"
#include"opencv2/highgui/highgui.hpp"
#include<opencv2/opencv.hpp>
#include"iostream"
using namespace cv;
void main()
{
	Mat img = imread("1.jpg");
	imshow("orignal jpg",img);
    vector<Mat>channel;
    split(img,channel);
    Mat B = channel.at(0);
    Mat G = channel.at(1);
    Mat R = channel.at(2);
    equalizeHist(B, B);
	equalizeHist(G, G);
    equalizeHist(R, R);
	merge(channel, img);
	imshow("hist",img);
	waitKey(0);
	destroyAllWindows();
}

效果如下

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 OpenCV折线图坐标轴,首先需要创建一个空白的图像作为背景,然后定义折线的数据点坐标。接下来,我们可以使用 OpenCV 的线段绘制函数来绘制坐标轴和折线。 首先,定义坐标轴的起点和终点,然后使用`cv2.line()`函数来绘制X轴和Y轴。接着,根据折线的数据点坐标,使用`cv2.line()`函数来绘制折线图。最后,可以使用`cv2.putText()`函数来添加坐标轴的标签。 具体代码如下: ```python import numpy as np import cv2 # 创建一个空白的图像 img = np.zeros((512, 512, 3), np.uint8) # 定义坐标轴的起点和终点 x_start = (50, 450) x_end = (450, 450) y_start = (50, 450) y_end = (50, 50) # 绘制X轴和Y轴 cv2.line(img, x_start, x_end, (255, 255, 255), 2) cv2.line(img, y_start, y_end, (255, 255, 255), 2) # 定义折线的数据点坐标 points = [(100, 400), (200, 300), (300, 450), (400, 200)] # 绘制折线图 for i in range(len(points) - 1): cv2.line(img, points[i], points[i+1], (0, 255, 0), 2) # 添加坐标轴的标签 cv2.putText(img, 'X', (480, 470), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2) cv2.putText(img, 'Y', (30, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2) # 显示图像 cv2.imshow('Line Chart', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 以上就是使用 OpenCV 折线图坐标轴的方法。通过定义坐标轴的起点和终点,以及折线的数据点坐标,再使用`cv2.line()`函数来绘制坐标轴和折线,最后添加坐标轴的标签,就可以在 OpenCV折线图坐标轴。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值