Opencv Cookbook阅读笔记:用直方图统计像素

Posted 牧马人夏峥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Opencv Cookbook阅读笔记:用直方图统计像素相关的知识,希望对你有一定的参考价值。


灰度直方图的定义

灰度直方图是灰度级的函数,描述图像中该灰度级的像素个数(或该灰度级像素出现的频率):其横坐标是灰度级,纵坐标表示图像中该灰度级出现的个数(频率)。

OpencvOpencv

#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

class Histogram1D

//定义一个处理单通道的类
private:
int histSize[1];//bin的数量
float hranges[2];//值范置
const float* ranges[1];//值范围的指针.指向常量的指针(所指对像不一定是个常量),不能通过指针修改其值
int channels[1];//通道数量


Mat getHistogram(const Mat &image)

//统计直方图
Mat hist;
calcHist(&image, 1,//一个图像的直方图
channels,//使用的通道
Mat(),//不使用掩码
hist,//作为结果的直方图
1,//一维直方图
histSize,
ranges
);

return hist;


public:
Histogram1D()

histSize[0] = 256;
hranges[0] = 0;//从0到256
hranges[1] = 256;

ranges[0] = hranges;

channels[0] = 0;


Mat getImageOfHistogram(const Mat &image, int zoom=1)

//zoom通道数
//画出直方图

Mat hist = getHistogram(image);

return getImageOfHistogram1(hist, zoom);


//定义为静态,不对成员变量进行操作
static Mat getImageOfHistogram1(const Mat &hist, int zoom)

//取得箱子的最大值和最小值
double maxVal = 0, minVal = 0;
minMaxLoc(hist, &minVal, &maxVal,0,0);

int histSize = hist.rows;
//用于显示的直方图
Mat histImg(histSize*zoom, histSize*zoom, CV_8U, Scalar(255));
//设置最高点为90%的箱子个数
int hpt = static_cast<int>(0.9*histSize);

//为每个箱子画垂线
for (int h = 0; h < histSize; h++)

float binVal = hist.at<float>(h);
if (binVal>0)

int intensity = static_cast<int>(binVal*hpt / maxVal);//相对高度
line(histImg, Point(h*zoom, histSize*zoom),
Point(h*zoom, (histSize - intensity)*zoom),
Scalar(0), zoom);



return histImg;

;

int main()


Mat image = imread("1.jpg");
//判断是否为空
Histogram1D h;
//Mat histo = h.getHistogram(image);
Mat histo = h.getImageOfHistogram(image);
//namedWindow("Histogram");
//imshow("Histogram",histo);
//输出二值图像
Mat thresholded;
threshold(image, thresholded, 200,//阈值
255,//对超过域值的像素赋值
THRESH_BINARY);//阈值化类型

imshow("threshold", thresholded);
waitKey(0);

return 0;

View Code


上面的程序是计算并画出单通下图像的直方图,主要就是calcHist函数。类似的可以定义一个计算彩色直方图的类。

OpencvOpencv

class ColorHistgoram

private:
int histSize[3];
float hranges[2];
const float*ranges[3];
int channels[3];
public:
ColorHistgoram()

histSize[0] = histSize[1] = histSize[2] = 256;
hranges[0] = 0;
hranges[1] = 256;

ranges[0] = hranges;
ranges[1] = hranges;
ranges[2] = hranges;

channels[0] = 0;
channels[1] = 1;
channels[2] = 2;


Mat getHistogram(const Mat &image)

Mat hist;

calcHist(&image,1, channels, Mat(), hist, 3, histSize, ranges);

return hist;

;

View Code


提高图像对比度

有两种方法,一是应用查找表来伸展直方图(有的强度值范围没有被利用),另一种是直方图均衡化(对所有可用的像素强度值都均衡使用)。


OpencvOpencv

//查找表函数
static Mat applyLookUp(const Mat &image, const Mat &lookup)

Mat result;
LUT(image, lookup, result);

return result;


//通过查找表提高图像的对比度
Mat stretch(const Mat &image, int minValue = 0)

Mat hist = getHistogram(image);

//找到直方图的左右限值
float imin;
for (imin=0;imin < histSize[0]; imin++)

//忽略数量较少的箱子
float x = hist.at<float>(imin);
if (x>minValue)
break;

int imax = histSize[0] - 1;
for (; imax >= 0; imax--)

if (hist.at<float>(imax)>minValue)
break;


//创建查找表
int dim(256);
Mat lookup(1,//一维
&dim, CV_8U);
for (int i = 0; i < 256; i++)

//
if (i < imin)lookup.at<uchar>(i) = 0;
else if (i>imax)lookup.at<uchar>(i) = 255;
else
lookup.at<uchar>(i) = cvRound(255.0*(i - imin) / (imax - imin));


Mat result;
result = applyLookUp(image, lookup);

return result;

View Code


 通过如下的函数可实现直方图均衡化。

//灰度图
equalizeHist(image, result);






以上是关于Opencv Cookbook阅读笔记:用直方图统计像素的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV 学习笔记(颜色直方图计算 calcHist)

OpenCV 学习笔记(直方图反向投影 BackProject)

OpenCV学习笔记13-图像直方图的介绍及代码实现

qt+opencv图像处理实现笔记

OpenCV CLAHE直方图均衡解析笔记

opencv学习笔记SVM+HOG