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

灰度直方图的定义

灰度直方图是灰度级的函数,描述图像中该灰度级的像素个数(或该灰度级像素出现的频率):其横坐标是灰度级,纵坐标表示图像中该灰度级出现的个数(频率)。
#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[];//bin的数量
float hranges[];//值范置
const float* ranges[];//值范围的指针.指向常量的指针(所指对像不一定是个常量),不能通过指针修改其值
int channels[];//通道数量 Mat getHistogram(const Mat &image)
{
//统计直方图
Mat hist;
calcHist(&image, ,//一个图像的直方图
channels,//使用的通道
Mat(),//不使用掩码
hist,//作为结果的直方图
,//一维直方图
histSize,
ranges
); return hist;
} public:
Histogram1D()
{
histSize[] = ;
hranges[] = ;//从0到256
hranges[] = ; ranges[] = hranges; channels[] = ;
} Mat getImageOfHistogram(const Mat &image, int zoom=)
{
//zoom通道数
//画出直方图 Mat hist = getHistogram(image); return getImageOfHistogram1(hist, zoom);
} //定义为静态,不对成员变量进行操作
static Mat getImageOfHistogram1(const Mat &hist, int zoom)
{
//取得箱子的最大值和最小值
double maxVal = , minVal = ;
minMaxLoc(hist, &minVal, &maxVal,,); int histSize = hist.rows;
//用于显示的直方图
Mat histImg(histSize*zoom, histSize*zoom, CV_8U, Scalar());
//设置最高点为90%的箱子个数
int hpt = static_cast<int>(0.9*histSize); //为每个箱子画垂线
for (int h = ; h < histSize; h++)
{
float binVal = hist.at<float>(h);
if (binVal>)
{
int intensity = static_cast<int>(binVal*hpt / maxVal);//相对高度
line(histImg, Point(h*zoom, histSize*zoom),
Point(h*zoom, (histSize - intensity)*zoom),
Scalar(), 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, ,//阈值
,//对超过域值的像素赋值
THRESH_BINARY);//阈值化类型 imshow("threshold", thresholded);
waitKey(); return ;
}

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

class ColorHistgoram
{
private:
int histSize[];
float hranges[];
const float*ranges[];
int channels[];
public:
ColorHistgoram()
{
histSize[] = histSize[] = histSize[] = ;
hranges[] = ;
hranges[] = ; ranges[] = hranges;
ranges[] = hranges;
ranges[] = hranges; channels[] = ;
channels[] = ;
channels[] = ;
} Mat getHistogram(const Mat &image)
{
Mat hist; calcHist(&image,, channels, Mat(), hist, , histSize, ranges); return hist;
}
};

提高图像对比度

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

//查找表函数
static Mat applyLookUp(const Mat &image, const Mat &lookup)
{
Mat result;
LUT(image, lookup, result); return result;
} //通过查找表提高图像的对比度
Mat stretch(const Mat &image, int minValue = )
{
Mat hist = getHistogram(image); //找到直方图的左右限值
float imin;
for (imin=;imin < histSize[]; imin++)
{
//忽略数量较少的箱子
float x = hist.at<float>(imin);
if (x>minValue)
break;
}
int imax = histSize[] - ;
for (; imax >= ; imax--)
{
if (hist.at<float>(imax)>minValue)
break;
} //创建查找表
int dim();
Mat lookup(,//一维
&dim, CV_8U);
for (int i = ; i < ; i++)
{
//
if (i < imin)lookup.at<uchar>(i) = ;
else if (i>imax)lookup.at<uchar>(i) = ;
else
lookup.at<uchar>(i) = cvRound(255.0*(i - imin) / (imax - imin));
} Mat result;
result = applyLookUp(image, lookup); return result;
}

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

//灰度图
equalizeHist(image, result);
上一篇:针对AJAX与JSONP的异同


下一篇:iOS多线程——GCD与NSOperation总结