OpenCV手工实现灰度及RGB直方图
手工实现灰度及RGB直方图 !库
1. 灰度图像直方图
算法
1. 图片灰度化;
2. 遍历Mat,统计各灰度级的像素个数;
3. 根据opencv画点线函数,绘制坐标轴及像素分布图
源码(编译环境:VS2017+OpenCV) 补充:三通道直方图(即RGB彩色图象直方图在后面)
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <opencv2/opencv.hpp> 5 #include <opencv2/imgproc/imgproc.hpp> 6 #include <opencv2/core/core.hpp> 7 #include <opencv2/highgui/highgui.hpp> 8 using namespace cv; 9 using namespace std; 10 //直方图绘制函数,参数vector<int> nums 是灰度图片256级灰度的像素个数 11 void drawHist(vector<int> nums) 12 { 13 Mat hist = Mat::zeros(600, 800, CV_8UC3); 14 auto Max = max_element(nums.begin(), nums.end());//max迭代器类型,最大数目 15 putText(hist, "Histogram", Point(150, 100), FONT_HERSHEY_DUPLEX, 1, Scalar(255, 255, 255)); 16 //*********绘制坐标系************// 17 Point o = Point(100, 550); 18 Point x = Point(700, 550); 19 Point y = Point(100, 150); 20 //x轴 21 line(hist, o, x, Scalar(255, 255, 255), 2, 8, 0); 22 //y轴 23 line(hist, o, y, Scalar(255, 255, 255), 2, 8, 0); 24 25 //********绘制灰度曲线***********// 26 Point pts[256]; 27 //生成坐标点 28 for (int i = 0; i < 256; i++) 29 { 30 pts[i].x = i * 2 + 100; 31 pts[i].y = 550 - int(nums[i]*(300.0/(*Max)));//归一化到[0, 300] 32 //显示横坐标 33 if ((i + 1) % 16 == 0) 34 { 35 string num = format("%d", i + 1); 36 putText(hist, num, Point(pts[i].x, 570), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255)); 37 } 38 } 39 //绘制线 40 for (int i = 1; i < 256; i++) 41 { 42 line(hist, pts[i - 1], pts[i], Scalar(0, 255, 0), 2); 43 } 44 //显示图像 45 imshow("直方图" ,hist); 46 } 47 //计算直方图,统计各灰度级像素个数 48 void calHist(const string img) 49 { 50 Mat src, grey; 51 //读取图象 52 src = imread(img); 53 if (!src.data) 54 { 55 cout << "Image: " + img + " 读取失败" << endl; 56 return; 57 } 58 //先转为灰度图 59 cvtColor(src, grey, COLOR_BGR2GRAY); 60 imshow("灰度图", grey); 61 //计算各灰度级像素个数 62 vector<int> nums(256); 63 for (int i = 0; i < grey.rows; i++) 64 { 65 uchar* p = grey.ptr<uchar>(i); 66 for (int j = 0; j < grey.cols; j++) 67 { 68 nums[p[j]]++; 69 } 70 } 71 drawHist(nums); 72 } 73 74 int main() 75 { 76 string img = "D:\\trashBox\\testIMG\\lena.bmp"; 77 calHist(img); 78 79 waitKey(0); 80 return 0; 81 }
效果图
直方图hist
2. RGB彩色图象直方图
源码
#include <iostream> #include <stdlib.h> #include <string> #include <algorithm> #include <opencv2/opencv.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/video.hpp> using namespace cv; using namespace std; //单通道图片直方图绘制 void drawHist(vector<int> nums) { Mat hist = Mat::zeros(600, 800, CV_8UC3); auto Max = max_element(nums.begin(), nums.end());//max迭代器类型,最大数目 putText(hist, "Histogram", Point(150, 100), FONT_HERSHEY_DUPLEX, 1, Scalar(255, 255, 255)); //*********绘制坐标系************// Point o = Point(100, 550); Point x = Point(700, 550); Point y = Point(100, 150); //x轴 line(hist, o, x, Scalar(255, 255, 255), 2, 8, 0); //y轴 line(hist, o, y, Scalar(255, 255, 255), 2, 8, 0); //********绘制灰度曲线***********// Point pts[256]; //生成坐标点 for (int i = 0; i < 256; i++) { pts[i].x = i * 2 + 100; pts[i].y = 550 - int(nums[i]*(300.0/(*Max)));//归一化到[0, 300] //显示横坐标 if ((i + 1) % 16 == 0) { string num = format("%d", i + 1); putText(hist, num, Point(pts[i].x, 570), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255)); } } //绘制线 for (int i = 1; i < 256; i++) { line(hist, pts[i - 1], pts[i], Scalar(0, 255, 0), 2); } //显示图像 imshow("直方图" ,hist); } //三通道图片直方图绘制 void drawHist(vector<int> &r, vector<int> &g, vector<int> &b) { Mat hist = Mat::zeros(600, 800, CV_8UC3); putText(hist, "Histogram", Point(150, 100), FONT_HERSHEY_DUPLEX, 1, Scalar(255, 255, 255)); //*********绘制坐标系************// Point o = Point(100, 550); Point x = Point(700, 550); Point y = Point(100, 150); //x轴 line(hist, o, x, Scalar(255, 255, 255), 2, 8, 0); //y轴 line(hist, o, y, Scalar(255, 255, 255), 2, 8, 0); //********绘制灰度曲线***********// auto Max_r = max_element(r.begin(), r.end()); auto Max_g = max_element(g.begin(), g.end()); auto Max_b = max_element(b.begin(), b.end()); Point pts[3][256]; //生成坐标点 for (int i = 0; i < 256; i++) { pts[0][i].x = i * 2 + 100; pts[0][i].y = 550 - int(r[i] * (300.0 / (*Max_r)));//归一化到[0, 300] pts[1][i].x = i * 2 + 100; pts[1][i].y = 550 - int(g[i] * (300.0 / (*Max_g)));//归一化到[0, 300] pts[2][i].x = i * 2 + 100; pts[2][i].y = 550 - int(b[i] * (300.0 / (*Max_b)));//归一化到[0, 300] //显示横坐标 if ((i + 1) % 16 == 0) { string num = format("%d", i + 1); putText(hist, num, Point(pts[0][i].x, 570), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255)); } } //绘制线 for (int i = 1; i < 256; i++) { line(hist, pts[0][i - 1], pts[0][i], Scalar(255, 0, 0), 2); line(hist, pts[1][i - 1], pts[1][i], Scalar(0, 255, 0), 2); line(hist, pts[2][i - 1], pts[2][i], Scalar(0, 0, 255), 2); } //显示图像 imshow("直方图", hist); } //灰度直方图计算 void calHist(const string img) { Mat src, grey; //读取图象 src = imread(img); if (!src.data) { cout << "Image: " + img + " 读取失败" << endl; return; } //先转为灰度图 cvtColor(src, grey, COLOR_BGR2GRAY); imshow("灰度图", grey); //计算各灰度级像素个数 vector<int> nums(256); for (int i = 0; i < grey.rows; i++) { uchar* p = grey.ptr<uchar>(i); for (int j = 0; j < grey.cols; j++) { nums[p[j]]++; } } drawHist(nums); } //多通道直方图计算 void calHist(const string img, int pattern) { Mat src, grey; //读取图象 src = imread(img); if (!src.data) { cout << "Image: " + img + " 读取失败" << endl; return; } imshow("原图像",src); //计算各灰度级像素个数 vector<int> r(256, 0); vector<int> g(256, 0); vector<int> b(256, 0); for (int i = 0; i < src.rows; i++) { uchar* p = src.ptr<uchar>(i); for (int j = 0; j < src.cols; j++) { r[p[j * 3 + 0]]++; g[p[j * 3 + 1]]++; b[p[j * 3 + 2]]++; } } drawHist(r, g, b); } int main() { string img = "D:\\trashBox\\testIMG\\tiger.jpg"; calHist(img);//计算灰度直方图 calHist(img, 0);//计算三色直方图 waitKey(0); return 0; }
算法
1. 遍历Mat,统计RGB三通道各灰度级的像素个数;
2. 根据opencv画点线函数,绘制坐标轴及像素分布图
效果
三色(三通道)直方图