OpenCV例項精解-直方圖與濾波器
阿新 • • 發佈:2019-01-05
原圖如下:
構造灰度直方圖:
/*構造灰度直方圖*/ void showHistoFunc() { //分割通道 vector<Mat> bgr; split(img, bgr); //建立有256個子區間的直方圖 int numbins = 256; //設定範圍(B,G,R),最後一個值不包含 float range[] = { 0, 256 }; const float *histRange = { range }; //計算每個直方圖 Mat b_hist, g_hist, r_hist; calcHist(&bgr[0], 1, 0, Mat(), b_hist, 1, &numbins, &histRange); calcHist(&bgr[1], 1, 0, Mat(), g_hist, 1, &numbins, &histRange); calcHist(&bgr[2], 1, 0, Mat(), r_hist, 1, &numbins, &histRange); //繪製直方圖 int width = 512; int height = 300; Mat histImage(height, width, CV_8UC3, Scalar(20,20,20)); //以灰色為基底建立影象 //從0到影象的高度歸一化直方圖 normalize(b_hist, b_hist, 0, height, NORM_MINMAX); normalize(g_hist, g_hist, 0, height, NORM_MINMAX); normalize(r_hist, r_hist, 0, height, NORM_MINMAX); int binStep = cvRound((float)width/(float)numbins); for (int i = 1; i < numbins; i++) { line(histImage, Point(binStep*(i - 1), height - cvRound(b_hist.at<float>(i - 1))), Point(binStep*(i), height - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0)); line(histImage, Point(binStep*(i - 1), height - cvRound(g_hist.at<float>(i - 1))), Point(binStep*(i), height - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0)); line(histImage, Point(binStep*(i - 1), height - cvRound(r_hist.at<float>(i - 1))), Point(binStep*(i), height - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255)); } imshow("Histogram", histImage); }
效果:
影象色彩均衡化(增強了對比度):
/*影象色彩均衡化:只需要均衡亮度通道(即Y通道)*/ void equalizeFunc() { Mat result; //BGR影象轉化為YCbCr Mat ycrcb; cvtColor(img, ycrcb, COLOR_BGR2YCrCb); //影象通道分離 vector<Mat> channels; split(ycrcb, channels); //只均衡y通道 equalizeHist(channels[0], channels[0]); //合併結果通道 merge(channels, ycrcb); //將YCrCB轉為BGR格式 cvtColor(ycrcb, result, COLOR_YCrCb2BGR); imshow("Equalized", result); }
效果:
實現Lomo效果
/*Lomo效果*/ void lomoFunc() { Mat result; const double exponential_e = std::exp(1.0); //建立一個包含256個元素的對映表 Mat lut(1, 256, CV_8UC1); for (int i = 0; i < 256; i++) { float x = (float)i / 256.0; lut.at<uchar>(i) = cvRound(256 * (1 / (1 + pow(exponential_e, -((x - 0.5) / 0.1))))); } //拆分影象通道,並只給紅色通道應用值變換 vector<Mat> bgr; split(img, bgr); LUT(bgr[2], lut, bgr[2]); //合併結果 merge(bgr, result); //建立暈暗的影象 Mat halo(img.rows, img.cols, CV_32FC3, Scalar(0.3, 0.3, 0.3)); //建立圓 circle(halo, Point(img.cols / 2, img.rows / 2), img.cols / 3, Scalar(1, 1, 1), -1); blur(halo, halo, Size(img.cols / 3, img.cols / 3)); //將結果轉化為浮點型 Mat resultf; result.convertTo(resultf, CV_32FC3); //將結果和halo相乘 multiply(resultf, halo, resultf); //轉化為8點陣圖像 resultf.convertTo(result, CV_8UC3); imshow("Lomograpy", result); }
效果:
實現卡通效果:
/* 卡通效果 */
void cartoonFunc()
{
//------edges---------//
//用中值濾波去除噪聲
Mat imgMedian;
medianBlur(img, imgMedian, 7);
//邊緣檢測
Mat imgCanny;
Canny(imgMedian, imgCanny, 50, 150);
//邊緣膨脹
Mat kernel = getStructuringElement(MORPH_RECT, Size(2, 2));
dilate(imgCanny, imgCanny, kernel);
//邊緣值縮放到1, 並將值翻轉
imgCanny = imgCanny / 255;
imgCanny = 1 - imgCanny;
//使用浮點值(允許在0和1之間相乘)
Mat imgCannyf;
imgCanny.convertTo(imgCannyf, CV_32FC3);
//模糊邊緣(實現平滑效果)
blur(imgCannyf, imgCannyf, Size(5, 5));
//------color---------//
//色彩均勻化(使用雙邊濾波器)
Mat imgBF;
bilateralFilter(img, imgBF, 9, 150.0, 150.0);
//截斷顏色
Mat result = imgBF / 25;
result = result * 25;
//------Merge color+edges---------//
//為邊緣建立3個通道
Mat imgCanny3c;
Mat cannyChannels[] = { imgCannyf, imgCannyf, imgCannyf };
merge(cannyChannels, 3, imgCanny3c);
//將結果轉化為浮點型
Mat resultf;
result.convertTo(resultf, CV_32FC3);
//顏色和邊緣矩陣相乘
multiply(resultf, imgCanny3c, resultf);
//轉化位8點陣圖像
resultf.convertTo(result, CV_8UC3);
imshow("cartoon", result);
}
效果: