zoukankan      html  css  js  c++  java
  • OpenCV(7)-图像直方图

    直方图定义可参考这里。图像的直方图用来表示图像像素的统计信息,它统计了图像每一个通道(如果是多通道)中,每个像素的个数(比例)。

    计算直方图

    OpenCV提供了直接计算直方图的函数

    void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false )
    

    images:输入图像。图的depth和size必须大小相同。
    nimages:输入图像个数
    channels:计算通道的索引。
    mask:可选。大小必须和images[i]相同,且是8-bit数组。非零的元素对应位置的像素用来计算直方图。
    hist:输出的直方图
    dims:直方图的维度
    histSize:每个维度直方图的大小
    ranges:每个维度,直方图的取值范围。
    uniform:直方图是每个维度宽度是否相同。
    accumulate:直方图是否累加。如果为true,每次计算不清空。

    例子:

    #include <iostream>
    #include <opencv2/opencv.hpp>
    
    using namespace cv;
    using namespace std;
    int main(int argc, char* argv[]){
    	const char* path = "";
    	Mat img = imread(path);
    	if (!img.data){
    		cout << "wrong image " << endl;
    		return -1;
    	}
    	//把BGR图像分割为单通道图像
    	vector<Mat> bgr_planes;
    	split(img, bgr_planes);
    	//计算直方图
    	vector<Mat> hist_image;
    	hist_image.resize(3);
    
    	//直方图统计像素类别数
    	const int histSize[] = { 255 };
    	float range[] = { 0, 255 };
    	const float* histRange = { range };
    	bool uniform = true;
    	bool accumulate = false;
    
    	const int channels[] = { 0 };
    	
    	calcHist(&bgr_planes[0], 1, channels, Mat(), hist_image[0], 1, histSize, &histRange, uniform, accumulate);
    	calcHist(&bgr_planes[1], 1, channels, Mat(), hist_image[1], 1, histSize, &histRange, uniform, accumulate);
    	calcHist(&bgr_planes[2], 1, channels, Mat(), hist_image[2], 1, histSize, &histRange, uniform, accumulate);
    	/// 将直方图高度归一化到范围 [ 0, histImage.rows ]
    	normalize(hist_image[0], hist_image[0], 0, hist_image[0].rows, NORM_MINMAX, -1, Mat());
    	normalize(hist_image[1], hist_image[1], 0, hist_image[1].rows, NORM_MINMAX, -1, Mat());
    	normalize(hist_image[2], hist_image[2], 0, hist_image[2].rows, NORM_MINMAX, -1, Mat());
    
    	// 创建直方图画布  
    	int hist_w = 400; int hist_h = 400;
    	int bin_w = cvRound((double)hist_w / histSize[0]);//每个像素宽度
    
    	Mat histImage(hist_h, hist_w, CV_8UC3, Scalar(0, 0, 0));
    
    	/// 在直方图画布上画出直方图。Mat坐标系,原点在左上角,习惯用的坐标系原点在左下角,因此高度要调整。即画布height - y
    	for (int i = 1; i < histSize[0]; i++)
    	{
    		//R
    		line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(hist_image[2].at<float>(i - 1))),
    			Point(bin_w*(i), hist_h - cvRound(hist_image[2].at<float>(i))),
    			Scalar(0, 0, 255), 2, 8, 0);
    		//G
    		line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(hist_image[1].at<float>(i - 1))),
    			Point(bin_w*(i), hist_h - cvRound(hist_image[1].at<float>(i))),
    			Scalar(0, 255, 0), 2, 8, 0);
    		//B
    		line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(hist_image[0].at<float>(i - 1))),
    			Point(bin_w*(i), hist_h - cvRound(hist_image[0].at<float>(i))),
    			Scalar(255, 0, 0), 2, 8, 0);
    	}
    
    	/// 显示直方图
    	imshow("Hist", histImage);
    	waitKey(0);
    	return 0;
    }
    

    直方图均衡化

    直方图均衡化是用来调整图像对比度的方法。它的思想是把某些像素值集中的区间分配到其他像素值上,在直方图上的表现就是拉伸了直方图,但是直方图的面积(图像总亮度)未改变,只是重新分配了而已。
    具体计算可以参考这里

    经过直方图均衡化后,图像的像素间差异减少,一些图像细节可能消失或减弱。

    OpenCV函数

    void equalizeHist(InputArray src, OutputArray dst)
    

    用来均衡化直方图。

    例子:

    #include <iostream>
    #include <opencv2/opencv.hpp>
    using namespace cv;
    int main(int argc, char* argv[]){
    
    	const char* path = "D:/image/sexy/yesky/20160318170735006671.jpg";
    	Mat img = imread(path);
    	if (!img.data)
    		return 1;
    	imshow("Original Image", img);
    
    	///三个通道直方图均衡化  
    	vector<Mat> rgb_planes;
    	split(img, rgb_planes);
    	equalizeHist(rgb_planes[0], rgb_planes[0]);
    	equalizeHist(rgb_planes[1], rgb_planes[1]);
    	equalizeHist(rgb_planes[2], rgb_planes[2]);
    
    	Mat new_img;
    	merge(rgb_planes, new_img);
    	imshow("New Image", new_img);
    	cvWaitKey(0);
    
    	return 0;
    }
    

    参考

    直方图计算
    直方图均衡化

  • 相关阅读:
    23、Linux实操篇——RPM与YUM
    22、Linux实操篇——进程管理(重点)
    21、Linux实操篇——网络配置
    20、Linux实操篇——磁盘分区、挂载
    19、Linux实操篇——组管理和权限管理
    18、实操篇——实用指令
    17、实操篇——用户管理
    UVALive 2521 Game Prediction 题解
    UVALive 2517 Moving Object Recognition(模拟)
    UVALive 2324 Human Gene Functions(动态规划)
  • 原文地址:https://www.cnblogs.com/korbin/p/5633965.html
Copyright © 2011-2022 走看看