天天看點

使用OpenCV實作卡通畫效果

一、卡通畫基本步驟  

1.邊緣檢測,并保留邊緣檢測的圖像
2.将輸入圖像和邊緣檢測圖像轉換為32位浮點圖像
3.将轉換後的輸入圖像和邊緣檢測圖像相乘(兩圖合并),合并後重新轉換為CV_8UC3
4.輸出最終的結果      

二、源代碼示範

/**
 * 實作卡通畫效果
 * 步驟:
 * 1.邊緣檢測,并保留邊緣檢測的圖像
 * 2.将輸入圖像和邊緣檢測圖像轉換為32位浮點圖像
 * 3.将轉換後的輸入圖像和邊緣檢測圖像相乘(兩圖合并),合并後重新轉換為CV_8UC3
 * 4.輸出最終的結果
 *
 * ps:為了達到較好的效果,可以調整邊緣檢測的門檻值,或者執行擴張的自定義形狀的卷積核的大小
 * @param inputImagePath
 */
void showCartoonImage(char *inputImagePath) {
    //加載原圖
    Mat src = imread(inputImagePath);
    //給圖檔應用高斯模糊(主要是為了去除自然界的噪聲)
    Mat imgMedian;
    //高斯模糊啊
    medianBlur(src, imgMedian, 7);
    //執行邊緣檢測
    Mat imgCanny;
    //此處門檻值可以嘗試用50~150
    Canny(imgMedian, imgCanny, 120, 130);
    //執行擴張,這裡的卷積核也可以自行調整試試看比如:放到到1~5
    Mat kernel = getStructuringElement(MORPH_RECT, Size(1, 1));//定義一個2x2的卷積核
    //使用擴張來連結斷開的邊緣
    dilate(imgCanny, imgCanny, kernel);
    //
    imgCanny = imgCanny / 255;
    imgCanny = 1 - imgCanny;
    //轉換為32位浮點數
    Mat imgCannyF;
    imgCanny.convertTo(imgCannyF, CV_32FC3);
    //中值模糊
    blur(imgCannyF, imgCannyF, Size(3, 3));
    //執行金字塔雙邊濾波,用于降噪、平滑、保持邊緣
    Mat imgBF;
    bilateralFilter(src, imgBF, 9, 150.0, 150.0);
    //
    Mat result = imgBF / 25;
    result = result * 25;
    //
    Mat imgCanny3c;
    Mat cannyChannels[] = {imgCannyF, imgCannyF, imgCannyF};
    merge(cannyChannels, 3, imgCanny3c);
    //轉為為32位浮點
    Mat resultF;
    result.convertTo(resultF, CV_32FC3);
    //相乘
    multiply(resultF, imgCanny3c, resultF);
    //将32位重新轉為8位
    resultF.convertTo(result, CV_8UC3);
    //展示圖檔
    //原圖
    imshow("src", src);
    //卡通畫效果
    imshow("cartoon", result);
    waitKey(0);

}      

三、對比圖檔展示

使用OpenCV實作卡通畫效果