<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>
结果