灰度图像直方图有256个项目,也叫箱子(bin)。如果把直方图所有的箱子进行累加,得到的结果就是像素的总数。若将直方图归一化,即所有的箱子累加和等于1,这时箱子的数值表示对应的像素数量占总数的百分比。
代码如下:
#include <iostream>#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/opencv.hpp>using namespace cv;using namespace std;int main(){ Mat image=imread("/Users/zhangxiaoyu/Desktop/2.png",0);//flags=0代表读取灰色图像 if(image.empty()) { cout<<"Error!cannot be read...../n"; return -1; } int nimages=1;//图片数量为1 int channels[1]={0};//通道数量 Mat outputHist;//输出直方图 int dims=1;//一维 int histSize[1]={256};//存放每个维度直方图尺寸的数组 float hranges[2]={0,255};//每一维数值的取值范围 const float *ranges[1]={hranges};//值范围的指针 //计算直方图 calcHist(&image, nimages, channels, Mat(), outputHist, dims, histSize, ranges); //循环遍历 for(int i=0;i<256;i++) std::cout<<"bin/value:"<<i<<"="<<outputHist.at<float>(i)<<std::endl; //画出直方图 int scale = 1; //直方图的图片 Mat histimage(histSize[0] * scale, histSize[0], CV_8U, cv::Scalar(255)); //找到最大值和最小值 double maxValue = 0; double minValue = 0; minMaxLoc(outputHist, &minValue, &maxValue, 0, 0); //测试 std::cout << minValue << std::endl; std::cout << maxValue << std::endl; //纵坐标缩放比例 double rate = (histSize[0] / maxValue)*0.9; for (int i = 0; i < histSize[0]; i++) { //得到每个i和箱子的值 float value = outputHist.at<float>(i); //画直线 line(histimage, Point(i*scale, histSize[0]), Point(i*scale, histSize[0] - value*rate), Scalar(0)); } namedWindow("hist"); imshow("histimage", histimage); //waitKey(0); Mat thresholded;//输出分割后的图像 threshold(image, thresholded, 166, 255, THRESH_BINARY); namedWindow("threshold_image"); imshow("threshold_image", thresholded); waitKey(0); }原始图片如下所示:
图像的灰度直方图为:
由上图可以看出,灰度直方图的两个“山峰”之间有“低谷”,可根据低谷的灰度直将图像分割,如下图所示:
基本可以看出,原始图像被分割为两部分,背景与前景。
新闻热点
疑难解答