最近在學習OpenCV的過程中,發現一本很好的書籍《Mastering OpenCV with Practical Computer Vision Projects》。在該書中,作者用很通俗易懂的方式闡述了如何在實際的電腦視覺工程項目中使用OpenCV(C++版本)。但是很遺憾,到目前為止該書還沒有中文版本。所以打算寫個系列部落格來分享自己看該書的一些見解。
電子書串連為《Mastering OpenCV with Practical Computer Vision Projects》
本書的配套源碼下載地址為:https://github.com/MasteringOpenCV/code - 使用OpenCV對映像進行卡通化(Cartoonifier)
如下圖所示,對映像進行卡通化操作的基本思想為:(1)對圖片中平坦的部分填充某種顏色或者說使平坦部分更加平滑;(2)在映像較強的邊緣處畫較厚的線條或者說使邊緣部分更加不平滑。
基本步驟為: 使中值濾波對映像進行平滑(Median filter) 使用邊緣檢測運算元檢測映像邊緣(Laplacian edge filter) 使用閾值法對邊緣映像進行二值處理
使用雙邊濾波(bilateral filter)對映像進行卡通化,雙邊濾波能在平滑映像平坦地區的同時很好的保留映像的邊緣資訊,但是其速度非常的慢。在該書中,作者先把映像縮小,進行處理,處理好之後再放大到原映像。
源碼:
void cartoonifyImage(Mat srcColor, Mat dst){ // 轉化為灰階映像 Mat srcGray; cvtColor(srcColor, srcGray, CV_BGR2GRAY); // 使用中值濾波去除映像雜訊 medianBlur(srcGray, srcGray, 7); Size size = srcColor.size(); Mat mask = Mat(size, CV_8U); Mat edges = Mat(size, CV_8U); Mat edges2; // Scharr是濾波器,其作用類似於邊緣檢測運算元,做差分運算 Scharr(srcGray, edges, CV_8U, 1, 0); Scharr(srcGray, edges2, CV_8U, 1, 0, -1); edges += edges2; // 自適應濾波 threshold(edges, mask, 12, 255, THRESH_BINARY_INV); medianBlur(mask, mask, 3); //imshow("edges", edges); //imshow("mask", mask); // 減小映像的大小為原來的一半,進行處理 Size smallSize; smallSize.width = size.width/2; smallSize.height = size.height/2; Mat smallImg = Mat(smallSize, CV_8UC3); resize(srcColor, smallImg, smallSize, 0,0, INTER_LINEAR); // 對減小之後的映像進行幾次雙邊濾波 Mat tmp = Mat(smallSize, CV_8UC3); int repetitions = 7; // Repetitions for strong cartoon effect. for (int i=0; i<repetitions; i++) { int size = 9; // Filter size. Has a large effect on speed. double sigmaColor = 9; // Filter color strength. double sigmaSpace = 7; // Positional strength. Effects speed. bilateralFilter(smallImg, tmp, size, sigmaColor, sigmaSpace); bilateralFilter(tmp, smallImg, size, sigmaColor, sigmaSpace); } // 對雙邊濾波之後的映像進行放大處理,放大到原來的尺寸 resize(smallImg, srcColor, size, 0,0, INTER_LINEAR); // 設定dst的資料全為0 memset((char*)dst.data, 0, dst.step * dst.rows); // 添加處理後的圖片和mask圖片到dst圖片 srcColor.copyTo(dst, mask);}