NO.8 C++ 直方图 & 卷积
作者:互联网
零蚀
直方图
-
直方图的绘制
- 在python中我们使用的直方图绘制是内部已经自己绘制好的,但是C++上的直方图,需要自己绘制直线的方式,在api上我们只能拿到对应的数据。
#include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main(){ Mat src = imread("../resource/ashin.jpg"); Mat gray; cvtColor(src,gray,COLOR_RGB2GRAY); imshow("src",src); Mat hist; // dst int channels=0; // int histSize=256; float range[]={0,255}; const float* h_rang = range; // 收集直方图的数据 , 源数据,数量,mask,通道index,数据,纬度,范围, calcHist(&gray,1, &channels,Mat(),hist,1,&histSize,&h_rang); /** 绘制直方图**/ Mat dst = Mat::zeros(Size(1200,500),CV_8UC3); // 数据归一化处理(将数据分布到0-400) Mat norm; normalize(hist,norm,0,400,NORM_MINMAX); // 将数据进行绘制 for (int a=0;a<256;++a){ int xOffset = a*4 + 100; float y = norm.at<float>(a); line(dst,Point(xOffset,500),Point(xOffset, static_cast<int>(500 - y)),Scalar(255,255,255,2),2); } imshow("dst",dst); waitKey(0); return 0; }
-
直方图均衡化
- 均衡化的计算方式:将灰度图像的值计算出来,然后转为出现的频率,计算累积概率,根据累计概率,均衡化。均衡化是为了让图像变得更加柔和,将一些突出的色值和总体颜色逼近。
// main #include <iostream> #include <opencv2/opencv.hpp> #include "equalization.h" int main(){ // 直方图均衡化 histEqualization("../resource/ashin.jpg","after"); return 0; } // 函数cpp // // Created by 零蚀 on 2020-11-15. // #include "equalization.h" void histEqualization(string path, string title) { Mat src = imread(path); Mat gray; cvtColor(src, gray, COLOR_RGB2GRAY); // 灰度的直方图数值 int channels = 0; const int size = 256; float range[] = {0, 255}; const float *ranges = range; Mat hist; calcHist(&gray, 1, &channels, Mat(), hist, 1, &size, &ranges); // 计算出概率 Mat radio = hist / (gray.rows * gray.cols); // 计算累计概率 Mat calculator(256,1,CV_32FC1); float s = 0; for (int i = 0; i < 256; i++) { float r= radio.at<float>(i); s+=r; calculator.at<float>(i)=s; } imshow("before", gray); // 根据累计概率均衡化 for(int m = 0;m<gray.rows;m++){ for (int n = 0; n < gray.cols; ++n) { int color = gray.at<uint8_t>(m,n); // 找到颜色对应的比例 float per = calculator.at<float>(color); // 均衡化(255 * 颜色累计比例) gray.at<uint8_t>(m,n) = static_cast<uint8_t>(255 * per); } } imshow(title, gray); waitKey(); }
-
直方图的匹配
- 直方图的主要流程,是通过计算原图像和目标图像的累计概率,得到两个图像的最小差异,然后进行映射。这就是直方图方式的匹配。它更像两个图像最小的差异色调融合。
#include "match.h int main(){ // 原图,映射的图片数据 histMatch("../resource/collapse.jpg","../resource/ashin.jpg"); return 0; } // match.cpp // // Created by 零蚀 on 2020-11-15. // #include "match.h" void getEqualHist(Mat *mat, Mat *calculator); void getMatchColor(Mat *srcSum, Mat *referSum,Mat *color); void oneChannelMatch(Mat* srcChannel,Mat* referChannel); void histMatch(string src_path, string refer_path) { // 获取原图和需要映射的图 Mat src = imread(src_path); Mat refer = imread(refer_path); imshow("srcGray", src); imshow("referGray", refer); // 通道切割 vector<Mat> chsSrc; vector<Mat> chsRefer; split(src, chsSrc); split(refer, chsRefer); // 灰度匹配 //Mat graySrc; //cvtColor(src,graySrc,COLOR_RGB2GRAY); //Mat grayRefer; //cvtColor(refer,grayRefer,COLOR_RGB2GRAY); //oneChannelMatch(&graySrc,&grayRefer); // 单通道匹配 oneChannelMatch(&chsSrc[0],&chsRefer[0]); oneChannelMatch(&chsSrc[1],&chsRefer[1]); oneChannelMatch(&chsSrc[2],&chsRefer[2]); // 多通道融合 merge(chsSrc,src); imshow("result", src); waitKey(); } /** * 单个通道的色值匹配 * @param srcChannel * @param referChannel */ void oneChannelMatch(Mat* srcChannel,Mat* referChannel){ Mat srcCalculator(256,1,CV_32FC1); getEqualHist(srcChannel,&srcCalculator); Mat referCalculator(256,1,CV_32FC1); getEqualHist(referChannel,&referCalculator); Mat color(256,1,CV_8UC1); getMatchColor(&srcCalculator,&referCalculator,&color); // 获取到最小的差值颜色 for(int row =0 ; row< srcChannel->rows;++row){ for (int col = 0; col < srcChannel->cols; ++col) { // 从原图中获取的颜色值 int colorValue = srcChannel->at<uint8_t>(row,col); //cout<< "colorValue="<<colorValue<<endl; // 获取对应目标的颜色值 uchar value = color.at<uchar>(colorValue); // 更新图像信息 srcChannel->at<uint8_t>(row,col)=value; } } } /** * 获取累计概率 * @param mat * @param calculator * @return */ void getEqualHist(Mat *mat, Mat *calculator) { // 灰度的直方图数值 int channels = 0; const int size = 256; float range[] = {0, 255}; const float *ranges = range; Mat hist; calcHist(mat, 1, &channels, Mat(), hist, 1, &size, &ranges); // 计算出概率 Mat radio = hist / (mat->rows * mat->cols); // 计算累计概率 //*calculator = Mat::zeros(256, 1, CV_32FC1); float s = 0; for (int i = 0; i < 256; i++) { float r = radio.at<float>(i); s += r; calculator->at<float>(i) = s; } } /** * 获取原图和目标图的累计概率差值 * @param srcSum * @param referSum * @param color */ void getMatchColor(Mat *srcSum, Mat *referSum,Mat *color) { for (int i = 0; i < 256; i++) { float src_radio = srcSum->at<float>(i); float aimValue = 10; int index = 0; cout<<"=========="<<endl; for (int j = 0; j < 256; ++j) { float refer_radio = referSum->at<float>(j); // 计算出累计概率的最小差值 float diffValue = abs(src_radio - refer_radio); if(diffValue < aimValue){ aimValue = diffValue; index = j; color->at<uint8_t>(i)= static_cast<uint8_t>(index); } } } }
- 如下图所示,左上角的原图,将右上角的色调融合进图片最终生成左下角的色调。灰度匹配
- 彩色匹配
[外链图片转存失败,源站可能
卷积
-
卷积
- 卷积主要是将图像的像素点和周围的像素进行一个运算,这样可以使图像较小色差(模糊)或者提升色值(锐化)。具体的原理看android对应部分。
void showFilter(string path) { Mat src = imread(path); Mat dst; // 构建kernel Mat kernel = (Mat_<char>(3, 3) << -1, -1, -1, -1, -1, 9, -1, -1, -1, -1); filter2D(src, dst, -1,kernel); //可以放大图片图片 namedWindow("src",WINDOW_NORMAL); imshow("src",src); imshow("dst",dst); waitKey(); }
- laplacian(拉普拉斯算子),拉普拉斯的算法呈现的信息比较细腻,不如canny那种,直接只保留了图像的边缘信息,而且是很明显的,拉普拉斯他会保留一些图像内部的细节信息。
void showLaplacian(string path){ Mat src = imread(path); Mat dst ; Laplacian(src,dst,CV_16S); // 由于计算可能导致溢出,需要使用一些算法加速(因为默认是8位uint8,而CV_16S是16位,所以需要加速,这样也能使图像更清晰。) convertScaleAbs(dst,dst); imshow("src",src); imshow("dst",dst); waitKey(); }
- Sobel & Scharr算子
void showSobel(string path){ Mat src = imread(path); Mat dst ; // Sobel(src,dst,-1,1,0); // 由于计算可能导致溢出,需要使用一些算法加速 // x方向 Sobel(src,dst,CV_16S,1,0); convertScaleAbs(dst,dst); // y方向 Mat dstY; Sobel(src,dstY,CV_16S,0,1); convertScaleAbs(dstY,dstY); Mat dst; add(dstX,dstY,dst); imshow("src",src); imshow("dst",dst); waitKey(); }
void showSobel(string path){ Mat src = imread(path); Mat dst ; Scharr(src,dst,CV_16S,1,0); // 由于计算可能导致溢出,需要使用一些算法加速 convertScaleAbs(dst,dst); imshow("src",src); imshow("dst",dst); waitKey(); }
标签:src,Mat,int,dst,float,C++,直方图,NO.8 来源: https://blog.csdn.net/qq_38315348/article/details/110259251