opencv灰度直方图
opencv灰度直方图
感觉这个原理就是数学统计吧,直接上代码,哪有错的或者不懂得地方,欢迎交流。
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
class jRect { //自己写了个jRect类,感觉是吃饱了撑着吧
public:
jRect(Point p,int w,int h)
:lefttop(p),rect_width(w),rect_height(h){}
Point lefttop;
int rect_width;
int rect_height;
};
void grayhist(Mat &input_gray,Mat &output_histogram, const Scalar &histColor,int hist_width=2);//绘制直方图
void drawjRect(Mat &input,jRect rect, const Scalar &jRectColor);//给直方图外边加个方框,为了好看
int main()
{
Mat src = imread("E://vs_program//images//Sakura_15.jpg");
imshow("src", src);
Mat src_gray;
cvtColor(src,src_gray,CV_BGR2GRAY);
imshow("src_gray", src_gray);
Mat output_histogram;
grayhist(src_gray, output_histogram,Scalar(255,0,255));
imshow("output_histogram", output_histogram);
waitKey(0);
return 0;
}
void grayhist(Mat &input_gray, Mat &output_histogram, const Scalar &histColor,int hist_width)
{
if (input_gray.type() != CV_8UC1)
{
cout << "input image's type is wrong." << endl;
return;
}
if (hist_width != 1 && hist_width != 2)
{
cout << "the hist_width is invalid,it should 2 or 1" << endl;
return;
}
double sumHistValue = input_gray.cols*input_gray.rows;
int hist[256] = {0};//存储每个灰度级像素的个数
for (int j = 0; j < input_gray.cols; j++)
{
for (int i = 0; i < input_gray.rows; i++)
{
int n= input_gray.at<uchar>(i, j);
hist[n] += 1;
}
}
output_histogram.create(Size(256 * hist_width + 2, 256 * hist_width + 2), CV_8UC3);//为了显示彩色,创建类型为CV_8UC3的矩阵体
output_histogram.setTo(255);//灰度直方图背景设置为白色
Point startPoint(0,0);
jRect boundary(startPoint, 256 * hist_width + 2, 256 * hist_width + 2);
drawjRect(output_histogram,boundary,Scalar(0,255,0));//画个绿色的框框
double maxhistHeigh = 0;
double histHeigh[256] = {0};//存储计算的每个灰度级中像素的数目占总像素的比率,用来计算 灰度直方图中 柱子的高度
for (int i = 0; i < 256; i++)
{
histHeigh[i]=(double)(hist[i]/ sumHistValue);
if (histHeigh[i] > maxhistHeigh)
maxhistHeigh = histHeigh[i];
}
int newHistHeight[256] = {0};//存储计算的 灰度直方图中 柱子的高度
for (int i = 0; i < 256; i++)
{
newHistHeight[i] = histHeigh[i] * ((250* hist_width) / maxhistHeigh +0.5);//最高的那个高度设置为250* hist_width,一个简单的比例换算。 这里四舍五入,有数据丢失
}
for (int j = 1; j <=256 * hist_width; j+=hist_width)//宽256 * hist_width + 2,在宽度为[1,256*hist_width]画柱子
{
for (int i = (boundary.rect_height-2); i >=(boundary.rect_height-2- newHistHeight[(j-1)/hist_width]) ; i--)//从下往上画柱子
{
switch (hist_width) {//直方图柱子的宽度:1个像素或者2个像素
case 1:
{
output_histogram.at<Vec3b>(i, j)[0] = histColor.val[0];
output_histogram.at<Vec3b>(i, j)[1] = histColor.val[1];
output_histogram.at<Vec3b>(i, j)[2] = histColor.val[2];
break;
}
case 2:
{
output_histogram.at<Vec3b>(i, j)[0] = histColor.val[0];
output_histogram.at<Vec3b>(i, j)[1] = histColor.val[1];
output_histogram.at<Vec3b>(i, j)[2] = histColor.val[2];
output_histogram.at<Vec3b>(i, j + 1)[0] = histColor.val[0];
output_histogram.at<Vec3b>(i, j + 1)[1] = histColor.val[1];
output_histogram.at<Vec3b>(i, j + 1)[2] = histColor.val[2];
break;
}
default:
break;
}
}
}
}
void drawjRect(Mat &input,jRect rect, const Scalar &jRectColor)
{
if (input.channels() != 3)
{
cout <<"the input image's channel:"<<input.channels()<<"."<< "please input three channels image." << endl;
return;
}
if (rect.lefttop.x<0 || rect.lefttop.x>input.cols || rect.lefttop.y<0 || rect.lefttop.y>input.rows)
{
cout << "your jRect's lefttop point is out of range" << endl;
return;
}
if (rect.rect_width<0 || (rect.lefttop.x+rect.rect_width)>input.cols || rect.rect_height<0 || (rect.lefttop.y+rect.rect_height)>input.rows)
{
cout << "your jRect's width or height is out of range" << endl;
return;
}
for (int j = rect.lefttop.x; j < (rect.lefttop.x+rect.rect_width); j++)//i hang y
{
input.at<Vec3b>(rect.lefttop.y,j)[0] = jRectColor.val[0];
input.at<Vec3b>(rect.lefttop.y,j)[1] = jRectColor.val[1];
input.at<Vec3b>(rect.lefttop.y,j)[2] = jRectColor.val[2];
input.at<Vec3b>(rect.lefttop.y+rect.rect_height-1, j)[0] = jRectColor.val[0];
input.at<Vec3b>(rect.lefttop.y + rect.rect_height - 1, j)[1] = jRectColor.val[1];
input.at<Vec3b>(rect.lefttop.y + rect.rect_height - 1, j)[2] = jRectColor.val[2];
}
for (int i = rect.lefttop.y; i < (rect.lefttop.y + rect.rect_height); i++)//i hang y
{
input.at<Vec3b>(i,rect.lefttop.x)[0] = jRectColor.val[0];
input.at<Vec3b>(i, rect.lefttop.x)[1] = jRectColor.val[1];
input.at<Vec3b>(i, rect.lefttop.x)[2] = jRectColor.val[2];
input.at<Vec3b>(i,rect.lefttop.x + rect.rect_width - 1)[0] = jRectColor.val[0];
input.at<Vec3b>(i, rect.lefttop.x + rect.rect_width - 1)[1] = jRectColor.val[1];
input.at<Vec3b>(i, rect.lefttop.x + rect.rect_width - 1)[2] = jRectColor.val[2];
}
}
效果:
原图和灰度图: