Non-photorealistic rendering(非真實感渲染)_使用opencv實現卡通化效果_ex2






這次要帶領大家來進行有趣的視訊卡通化濾鏡功能


首先  我們觀察一下

這個效果   主要是  著重於   邊緣(界)提取

第一階段 - 邊界偵測

一般在電腦視覺中,常被用到的是我們的Canny圖像邊界偵測!!!

這是由 John F.Canny 所開發的 , 因而以其名來命名。

此方法滿足下列三種條件:

(1) 低錯誤率 : 僅在存在的邊界上,偵測效果不錯。

(2)局部化良好 : 偵測到像素邊界之間的距離最小,實際邊界的pixel也最小(minimal)

(3)簡單反應 : 每個邊界只有一個偵測效果。

偵測步驟如下 :

1. 用  Gauassian Filter 去 過濾 除去 雜訊

2. 用 類似 Sobel方法 尋找圖像傾斜度的強度。

3. 採用 非最大壓制( non-maximum suppression) , 這個步驟會移除認為不是邊界的像素,所以會只留下細線。

4.滯後作用 : 這是最後步驟使用兩種臨界法

如果 pixel傾斜度 高於 上臨界值就會被認為是邊界。
如果pixel 傾斜度 低於 下臨界值就捨去
如果pixel傾斜度介於兩臨界值間,而相連的pixel強度高於上臨界值就被認定為邊界。

原創者 John F.Canny

認為  上下 臨界值分別是  2:1   與 3:1


【程式碼】


#include<opencv/highgui.h>
#include <opencv/cv.h>
#include <iostream>
using namespace cv;
using namespace std;


int main(int argc, char** argv)
{
    IplImage *frame, *GrayFrame;
    //VideoCapture cap(0); // open the default camera
    CvCapture *capture = cvCaptureFromCAM(0);//cvCaptureFromCAM()其實跟cvCreateCameraCapture()一模一樣
    //被OpenCV定義成 #define cvCaptureFromCAM cvCreateCameraCapture
    //所以,當用cvCaptureFromCAM()會自動取代成cvCreateCameraCapture()
    //而在視訊裝置的使用上也大有學問,一般視訊裝置是0是自動偵測
    //若有多台攝影機,則自己再額外多定義即可
    //例如 : CvCapture * cap2 = cvCreateCameraCapture(1);//第二個視訊

    //frame = cvQueryFrame(capture);//從攝像頭或者文件中抓取一幀,然後解壓並返回這一幀。
    while (NULL == (frame = cvQueryFrame(capture)));
    GrayFrame = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);
    cvNamedWindow("Canny_WebCam", 0);

    while (true)    //infinite loop 
    {
        frame = cvQueryFrame(capture);//單幀讀入視頻。

        //更改色度,採色變灰階
        cvCvtColor(frame, GrayFrame, CV_BGR2GRAY);  //執行這行的用意  是因為 Canny只能接受灰階圖(單通道)
        //cvCvtColor(欲轉換圖檔 , 接受轉換後圖檔  ,轉換類別)

        cvCanny(GrayFrame, GrayFrame, 50, 180, 3); // cvCanny(in , out , low , top ,s);
        // cvCanny(單通道原圖輸入,單通道存儲邊緣的輸出圖像,第一個閾值(小的):控制邊緣連接,第二個閾值(大的):控制邊緣的初始分割,Sobel 算子内核大小(填三) )
        cvShowImage("Canny_WebCam", GrayFrame);
        if (cvWaitKey(10) >= 0)
            break;
    }
    cvReleaseCapture(&capture);    //釋放  
    return 0;
}



效果




第二階段 -影像銳化 


【程式碼】


#include<opencv/highgui.h>
#include <opencv/cv.h>
#include <iostream>
using namespace cv;
using namespace std;
IplImage *frame, *GrayFrame;

int main(int argc, char** argv)
{
    //VideoCapture cap(0); // open the default camera
    CvCapture *capture = cvCaptureFromCAM(0);//cvCaptureFromCAM()其實跟cvCreateCameraCapture()一模一樣
    //被OpenCV定義成 #define cvCaptureFromCAM cvCreateCameraCapture
    //所以,當用cvCaptureFromCAM()會自動取代成cvCreateCameraCapture()
    //而在視訊裝置的使用上也大有學問,一般視訊裝置是0是自動偵測
    //若有多台攝影機,則自己再額外多定義即可
    //例如 : CvCapture * cap2 = cvCreateCameraCapture(1);//第二個視訊

    CvMat* kernel = 0;
    kernel = cvCreateMat(3, 3, CV_32FC1);

    cvSet2D(kernel, 0, 0, cvRealScalar(-1));
    cvSet2D(kernel, 0, 1, cvRealScalar(-1));
    cvSet2D(kernel, 0, 2, cvRealScalar(-1));
    cvSet2D(kernel, 1, 0, cvRealScalar(-1));
    cvSet2D(kernel, 1, 1, cvRealScalar(9));
    cvSet2D(kernel, 1, 2, cvRealScalar(-1));
    cvSet2D(kernel, 2, 0, cvRealScalar(-1));
    cvSet2D(kernel, 2, 1, cvRealScalar(-1));
    cvSet2D(kernel, 2, 2, cvRealScalar(-1));

    //frame = cvQueryFrame(capture);//從攝像頭或者文件中抓取一幀,然後解壓並返回這一幀。
    while (NULL == (frame = cvQueryFrame(capture)));
    GrayFrame = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);
    cvNamedWindow("sharping_webcam", 0);

    while (true)    //infinite loop 
    {
        frame = cvQueryFrame(capture);//單幀讀入視頻。

        //更改色度,採色變灰階
        cvCvtColor(frame, GrayFrame, CV_BGR2GRAY);  //執行這行的用意  是因為 Canny只能接受灰階圖(單通道)
        //cvCvtColor(欲轉換圖檔 , 接受轉換後圖檔  ,轉換類別)

        //cvCanny(GrayFrame, GrayFrame, 50, 150, 3); // cvCanny(in , out , low , top ,s);
        // cvCanny(單通道原圖輸入,單通道存儲邊緣的輸出圖像,第一個閾值(小的):控制邊緣連接,第二個閾值(大的):控制邊緣的初始分割,Sobel 算子内核大小(填三) )
        cvFilter2D(GrayFrame, GrayFrame, kernel);//高通濾波

        cvShowImage("sharping_webcam", GrayFrame);
        if (cvWaitKey(10) >= 0)
            break;
    }
    cvReleaseCapture(&capture);    //  
    return 0;
}


這是針對 單通道 灰階 進行  銳化的處理

效果

還未銳化效果


已銳化



第三階段 - (Canny+銳化)融合在彩影視訊 



【程式碼】


#include<opencv/highgui.h>
#include <opencv/cv.h>
#include <iostream>
using namespace cv;
using namespace std;
IplImage *frame, *GrayFrame, *dst;

int main(int argc, char** argv)
{

    CvCapture *capture = cvCaptureFromCAM(0);//cvCaptureFromCAM()其實跟cvCreateCameraCapture()一模一樣
    //被OpenCV定義成 #define cvCaptureFromCAM cvCreateCameraCapture
    //所以,當用cvCaptureFromCAM()會自動取代成cvCreateCameraCapture()
    //而在視訊裝置的使用上也大有學問,一般視訊裝置是0是自動偵測
    //若有多台攝影機,則自己再額外多定義即可
    //例如 : CvCapture * cap2 = cvCreateCameraCapture(1);//第二個視訊
    CvMat* kernel = 0;
    kernel = cvCreateMat(3, 3, CV_32FC1);

    cvSet2D(kernel, 0, 0, cvRealScalar(-1));
    cvSet2D(kernel, 0, 1, cvRealScalar(-1));
    cvSet2D(kernel, 0, 2, cvRealScalar(-1));
    cvSet2D(kernel, 1, 0, cvRealScalar(-1));
    cvSet2D(kernel, 1, 1, cvRealScalar(9));
    cvSet2D(kernel, 1, 2, cvRealScalar(-1));
    cvSet2D(kernel, 2, 0, cvRealScalar(-1));
    cvSet2D(kernel, 2, 1, cvRealScalar(-1));
    cvSet2D(kernel, 2, 2, cvRealScalar(-1));
    //frame = cvQueryFrame(capture);//從攝像頭或者文件中抓取一幀,然後解壓並返回這一幀。
    while (NULL == (frame = cvQueryFrame(capture))); //
    GrayFrame = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);
    cvNamedWindow("卡通化濾鏡", 0);

    while (true)    //infinite loop 
    {
        frame = cvQueryFrame(capture);//單幀讀入視頻。

        //更改色度,採色變灰階
        cvCvtColor(frame, GrayFrame, CV_BGR2GRAY);  //執行這行的用意  是因為 Canny只能接受灰階圖(單通道)
        //cvCvtColor(欲轉換圖檔 , 接受轉換後圖檔  ,轉換類別)
        cvFilter2D(frame, frame, kernel);
        dst = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3);  //  多一個  dst變數結構  存  彩色視訊

        cvCanny(GrayFrame, GrayFrame, 50, 180, 3); // cvCanny(in , out , low , top ,s);
        // cvCanny(單通道原圖輸入,單通道存儲邊緣的輸出圖像,第一個閾值(小的):控制邊緣連接,第二個閾值(大的):控制邊緣的初始分割,Sobel 算子内核大小(填三) )
        cvNot(GrayFrame, GrayFrame);  //黑背白邊  ==> 白背黑邊
        cvSetZero(dst); // 對圖像pixel自動設置為零,相當於cvSet(0.0)  清空数组 
        cvCopy(frame, dst, GrayFrame);  // cvCopy(輸入數組,輸出數組,);
        //cvCopy( const CvArr* src, CvArr* dst, const CvArr* mask=NULL );
        cvResizeWindow("卡通化濾鏡", 800, 600);  //

        cvShowImage("卡通化濾鏡", dst);
        if (cvWaitKey(10) >= 0)
            break;
    }
    cvReleaseCapture(&capture);    //釋放  
    return 0;
}

效果





以上是本次    影像演算流程分享







留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

(2021年度)駕訓學科筆試準備題庫歸納分析_法規是非題