直方图规范化的opencv的实现
来源:互联网 发布:h3c路由配置端口ip网关 编辑:程序博客网 时间:2024/06/05 18:58
直方图规范化也叫规定化。通过直方图的规定,能够把两幅图像的色调拉成一样。
数学原理在网上很多可以找到。这里说一下实现过程步骤和opencv的C++实现。
上表一行行看下来,大部分应该没什么问题。SML映射看的是原始累计直方图的值最相近的规定累计直方图的位置,(比如0.14在下面找最接近的是0.19,是就是3).
然后下面就很简单了,灰度0映射到灰度3,灰度1映射到灰度4。。。
代码还是比较简单的,就是网上搜了一下也没有,OPENCV本身也没有封装。就自己写了一个,和大家共享。
#include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> #include <iostream> using namespace std;using namespace cv;bool Cal_Hist(Mat Gray_img, MatND &hist){int bins = 256;int hist_size[] = { bins };float range[] = { 0, 256 };const float* ranges[] = { range };int channels[] = { 0 };//计算直方图 calcHist(&Gray_img, 1, channels, Mat(), // do not use mask hist, 1, hist_size, ranges,true, // the histogram is uniform false);if (hist.data == 0) return false;return true;}void DrawGrayHist(const char* pTitle, MatND& hist){int hist_height = 256;int bins = 256;double max_val; //直方图的最大值 int scale = 2; //直方图的宽度 minMaxLoc(hist, 0, &max_val, 0, 0); //计算直方图最大值 Mat hist_img = Mat::zeros(hist_height, bins*scale, CV_8UC3); //创建一个直方图图像并初始化为0 for (int i = 0; i<bins; i++){float bin_val = hist.at<float>(i); // 第i灰度级上的数 int intensity = cvRound(bin_val*hist_height / max_val); //要绘制的高度 //填充第i灰度级的数据 rectangle(hist_img, Point(i*scale, hist_height - 1),Point((i + 1)*scale - 1, hist_height - intensity),CV_RGB(255, 255, 255));}imshow(pTitle, hist_img);}void one_channel_hist_specify(Mat input_img, Mat dst_img, Mat &output_img)//单通道{int i,j; //计算输入,规定图像的直方图MatND input_hist, dst_hist;Cal_Hist(input_img, input_hist);Cal_Hist(dst_img, dst_hist);//计算概率直方图MatND input_p_hist, dst_p_hist;input_p_hist = MatND::zeros(input_hist.size[0], input_hist.size[1], CV_32FC1);//原始概率直方图dst_p_hist = MatND::zeros(dst_hist.size[0], dst_hist.size[1], CV_32FC1);//规定概率直方图float input_totalnum = 0;float dst_totalnum = 0;for (i = 0; i < input_hist.rows; i++)input_totalnum += input_hist.at<float>(i);for (i = 0; i < dst_hist.rows; i++)dst_totalnum += dst_hist.at<float>(i);for (i = 0; i < input_hist.rows; i++)input_p_hist.at<float>(i) = input_hist.at<float>(i) / input_totalnum;for (i = 0; i < dst_hist.rows; i++)dst_p_hist.at<float>(i) = dst_hist.at<float>(i) / dst_totalnum;//计算累计直方图MatND input_c_hist, dst_c_hist;input_c_hist = MatND::zeros(input_hist.size[0], input_hist.size[1], CV_32FC1);//原始累计直方图dst_c_hist = MatND::zeros(dst_hist.size[0], dst_hist.size[1], CV_32FC1);//规定累计直方图float input_accum_p = 0;float dst_accum_p = 0;for (i = 0; i < input_hist.rows; i++){input_accum_p += input_p_hist.at<float>(i);input_c_hist.at<float>(i) = input_accum_p;}for (i = 0; i < dst_hist.rows; i++){dst_accum_p += dst_p_hist.at<float>(i);dst_c_hist.at<float>(i) = dst_accum_p;}//计算单映射规则MatND SML = MatND::zeros(input_hist.size[0], input_hist.size[1], CV_32FC1);//SML单映射规则for (i = 0; i < input_c_hist.rows; i++){int minind = 0;float minval = 1;for (j = 0; j < dst_c_hist.rows; j++){float abssub = abs(input_c_hist.at<float>(i)-dst_c_hist.at<float>(j));if (abssub < minval){minval = abssub;minind = j;}}SML.at<float>(i) = minind;}//计算输出图像Mat outimg = Mat::zeros(input_img.size[0], input_img.size[1], CV_8U);for (i = 0; i < input_img.rows; i++){for (j = 0; j < input_img.cols; j++){outimg.at<uchar>(i, j) = SML.at<float>(input_img.at<uchar>(i, j));}}outimg.copyTo(output_img);//计算输出图像直方图//MatND output_hist;//Cal_Hist(output_img, output_hist);//DrawGrayHist("input_hist", input_hist);//DrawGrayHist("dst_hist", dst_hist);//DrawGrayHist("output_hist", output_hist);}void three_channel_hist_specify(Mat input_img, Mat dst_img, Mat &output_img)//三通道{//Mat src = imread("path", 1); //读入目标图像 Mat out_img(input_img.rows, input_img.cols, CV_8UC3); //用来存储目的图片的矩阵 //Mat数组来存车分离后的三个通道,每个通道都初始化为0; Mat input_planes[] = { Mat::zeros(input_img.size(), CV_8UC1), Mat::zeros(input_img.size(), CV_8UC1), Mat::zeros(input_img.size(), CV_8UC1) };Mat dst_planes[] = { Mat::zeros(dst_img.size(), CV_8UC1), Mat::zeros(dst_img.size(), CV_8UC1), Mat::zeros(dst_img.size(), CV_8UC1) };//多通道分成3个单通道,BGRsplit(input_img, input_planes);split(dst_img, dst_planes);Mat B_output_img, G_output_img, R_output_img;one_channel_hist_specify(input_planes[0], dst_planes[0], B_output_img);one_channel_hist_specify(input_planes[1], dst_planes[1], G_output_img);one_channel_hist_specify(input_planes[2], dst_planes[2], R_output_img);Mat output_planes[3];output_planes[0] = B_output_img;output_planes[1] = G_output_img;output_planes[2] = R_output_img;merge(output_planes,3, out_img); //通道合并out_img.copyTo(output_img);}int main(){Mat src, gray, src2, gray2;//src=imread("D://input//buti.jpg"); src = imread("F:\\大海.jpg");cvtColor(src, gray, CV_RGB2GRAY); //转换成灰度图 src2 = imread("F:\\沙漠.jpg");cvtColor(src2, gray2, CV_RGB2GRAY); //转换成灰度图 MatND hist2;imshow("Source", src);//imshow( "Gray Histogram", hist_img ); imshow("Source2", src2);Mat output_img;three_channel_hist_specify(src, src2, output_img);imshow("5", output_img);//DrawGrayHist("2", hist2);waitKey();return 0;}
原图:
规定图:
转化结果:
2 0
- 直方图规范化的opencv的实现
- 直方图的Opencv实现
- 关于直方图规范化的C++编程实现_2015_7_24
- 彩色直方图均衡的OpenCV实现
- 基于直方图的图像检索OpenCV实现
- OpenCV直方图的使用
- opencv直方图的应用
- OpenCV直方图的使用
- OpenCV-统计图像的直方图,绘制直方图
- 【图像处理】基于OpenCV底层实现的直方图匹配
- opencv中直方图的理解
- opencv中直方图的理解
- opencv 3.0 直方图的计算
- opencv中直方图的理解
- 【opencv】之直方图的应用
- 【OpenCV】绘制图像的直方图
- opencv实现灰度图像的直方图点计算以及灰度直方图显示
- 的规范化
- Ananagrams Uva156
- Base入门篇
- 02C#一些基础知识
- 版本号闲谈
- 胎压项目架构的总结
- 直方图规范化的opencv的实现
- 5 状态机
- Tomcat 7.0 win7 64位免安装解压版 安装及配置
- android 自定义View开发实战(五) TextView滚动显示
- Eclipse:unable to connect to host 127.0.0.1 on port 7055
- Stream API
- 设备管理器中 停用启用设备后设备上有YB 错误代码Code 31
- 1027. 打印沙漏(20)
- Spring学习笔记(二)