Opencv Cookbook阅读笔记:用直方图统计像素
Posted 牧马人夏峥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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[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函数。类似的可以定义一个计算彩色直方图的类。
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
提高图像对比度
有两种方法,一是应用查找表来伸展直方图(有的强度值范围没有被利用),另一种是直方图均衡化(对所有可用的像素强度值都均衡使用)。
//查找表函数
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阅读笔记:用直方图统计像素的主要内容,如果未能解决你的问题,请参考以下文章