标签:
#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; }
上面的程序是计算并画出单通下图像的直方图,主要就是calcHist函数。类似的可以定义一个计算彩色直方图的类。
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; } };
提高图像对比度
有两种方法,一是应用查找表来伸展直方图(有的强度值范围没有被利用),另一种是直方图均衡化(对所有可用的像素强度值都均衡使用)。
//查找表函数 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; }
通过如下的函数可实现直方图均衡化。
//灰度图 equalizeHist(image, result);
Opencv Cookbook阅读笔记(四):用直方图统计像素
标签:
原文地址:http://www.cnblogs.com/573177885qq/p/5672841.html