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;
}
效果
以上是本次 影像演算流程分享
留言
張貼留言