<span style="font-size:18px;">圖像卡通化就是讓邊緣變粗,平坦的地方更平坦,所以就需要邊緣檢測,和濾波。</span>
<span style="font-size:18px;">1,當然爲了得到更好的效果一般都要先進行濾波,例如使用對椒鹽噪聲很有效的中值濾波。</span>
<span style="font-size:18px;">2,</span><span style="font-size:18px; font-family: Arial, Helvetica, sans-serif;">爲了得到邊緣檢測結果就用了laplacian濾波,我們知道這個是高通濾波,同時它相比較其他例如canny等在視頻處理中更穩定。</span>
<span style="font-size:18px;">3,對於邊緣檢測結果,我們需要進行二值化,用來得到一個mask爲了後面使用</span>
<span style="font-size:18px;">4,前面有了讓邊緣更粗的結果,那接下來就要有平坦部分更平坦了,所以採用了雙邊濾波(它能夠平滑平坦部分的同時保持邊緣的效果),爲了降低雙邊濾波的計算,圖像尺寸降低一倍處理,處理完畢之後恢復大小。</span>
<span style="font-size:18px;">5,最後就是融合兩個階段的結果,讓mask覆蓋到雙邊濾波的結果圖上。</span>
<span style="font-size:18px;">
</span>
<span style="font-size:18px;">void cartoonifyImage(const Mat& srcImg,Mat& resultImg ){
//to reduce noise
Mat grayImg;
cvtColor(srcImg,grayImg,CV_BGR2GRAY);
medianBlur(grayImg,grayImg,7);
Mat edgeImg;
Laplacian(grayImg,edgeImg,CV_8U,5);
Mat maskImg;
threshold(edgeImg,maskImg,80,255,THRESH_BINARY_INV);
//to reduce compute time
Size sizeSrc = srcImg.size();
Size sizeSmall ;
sizeSmall.width = sizeSrc.width / 2;
sizeSmall.height = sizeSrc.height / 2;
Mat smallImg = Mat(sizeSmall,CV_8UC3);
resize(srcImg,smallImg,sizeSmall,0,0,INTER_LINEAR);
Mat tempImg = Mat(sizeSmall,CV_8UC3);
int repetition = 7;
for (int k=0;k<repetition;k++){
bilateralFilter(smallImg,tempImg,9,9,7);
bilateralFilter(tempImg,smallImg,9,9,7);
}
Mat bigImg;
resize(smallImg,bigImg,sizeSrc,0,0,INTER_LINEAR);
resultImg.setTo(0);
bigImg.copyTo(resultImg,maskImg);
}</span>
結果