opecv cartoon(外星人模式)

////"cartoon.h"

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
void cartoonifyImage(const Mat,Mat&);

///"cartoon.cpp"

#include<opencv2/opencv.hpp>
#include<iostream>
#include"cartoon.h"
int flag_CARTOONorMONSTER = 0;
void cartoonifyImage(const Mat srcImage,Mat &dstImage)
{
Mat mask;
Mat edges,edges2;
if(!flag_CARTOONorMONSTER){
Mat gray;
cvtColor(srcImage,gray,CV_BGR2GRAY);//轉化成灰度值
const int MEDIAN_BLUR_FILTER_SIZE = 7;
medianBlur(gray,gray,MEDIAN_BLUR_FILTER_SIZE);//中值濾波
const int LAPLACIAN_FILTER_SIZE = 5;
Laplacian(gray,edges,CV_8U,LAPLACIAN_FILTER_SIZE);//拉普拉斯邊緣濾波
const int EDGES_THRESHOLD = 80;
threshold(edges,mask,EDGES_THRESHOLD,255,THRESH_BINARY_INV);//類似於素描的樣子了
}
/* if(flag_CARTOONorMONSTER){
Mat gray;
cvtColor(srcImage,gray,CV_BGR2GRAY);
const int MEDIAN_BLUR_FILTER_SIZE = 7;
medianBlur(gray,gray,MEDIAN_BLUR_FILTER_SIZE);

Scharr(gray,edges,CV_8U,1,0);
Scharr(gray,edges2,CV_8U,1,0,-1);
edges += edges2;
const int EVIL_EDGE_THRESHOLD = 12;
threshold(edges,mask,EVIL_EDGE_THRESHOLD,255,THRESH_BINARY_INV);
medianBlur(mask,mask,3);
}*/
Size size = srcImage.size();
Size smallSize;
smallSize.width = size.width/2;
smallSize.height = size.height/2;
Mat smallImg = Mat(smallSize,CV_8UC3);
resize(srcImage,smallImg,smallSize,0,0,INTER_LINEAR);//將圖變小,低分辨率下使用雙邊濾波器
Mat temp = Mat(smallSize,CV_8UC3);
int repetitions = 7;
for(int i = 0;i<repetitions;i++){
int ksize = 9;
double sigmaColor = 9;
double sigmaSpace = 7;
bilateralFilter(smallImg,temp,ksize,sigmaColor,sigmaSpace);//雙邊濾波
bilateralFilter(temp,smallImg,ksize,sigmaColor,sigmaSpace);//多個小型濾波器代替大型濾波器,提高速度
}
Mat bigImg;
resize(smallImg,bigImg,size,0,0,INTER_LINEAR);
dstImage.setTo(0);
bigImg.copyTo(dstImage,mask);//卡通的樣子
/**********開始畫人臉輪廓**************/
Mat faceOutline = Mat::zeros(size,CV_8UC3);
Scalar color = CV_RGB(255,255,0);
int thickness = 4;
int Sw = size.width;
int Sh = size.height;
int faceH = Sw/2*70/100;
int faceW = faceH*72/100;
ellipse(faceOutline,Point(Sw/2,Sh/2),Size(faceW,faceH),0,0,360,color,thickness,CV_AA);
int eyeW = faceW*23/100;
int eyeH = faceH*11/100;
int eyeX = faceW*48/100;
int eyeY = faceH*13/100;
Size eyeSize = Size(eyeW,eyeH);
int eyeA = 15;
int eyeYshift = 11;
ellipse(faceOutline,Point(Sw/2-eyeX,Sh/2-eyeY),eyeSize,0,180+eyeA,360-eyeA,color,thickness,CV_AA);
ellipse(faceOutline,Point(Sw/2-eyeX,Sh/2-eyeY-eyeYshift),eyeSize,0,0+eyeA,180-eyeA,color,thickness,CV_AA);
ellipse(faceOutline,Point(Sw/2+eyeX,Sh/2-eyeY),eyeSize,0,180+eyeA,360-eyeA,color,thickness,CV_AA);
ellipse(faceOutline,Point(Sw/2+eyeX,Sh/2-eyeY-eyeYshift),eyeSize,0,0+eyeA,180-eyeA,color,thickness,CV_AA);
int mouthY = faceH*48/100;
int mouthW = faceW*45/100;
int mouthH = faceH*6/100;
ellipse(faceOutline,Point(Sw/2,Sh/2+mouthY),Size(mouthW,mouthH),0,0,180,color,thickness,CV_AA);

int fontFace = FONT_HERSHEY_COMPLEX;
float fontScale = 1.0f;
int fontThickness = 2;
char *szMsg = "Put your face here";
putText(faceOutline,szMsg,Point(Sw*23/100,Sh*10/100),fontFace,fontScale,color,fontThickness,CV_AA);
addWeighted(dstImage,1.0,faceOutline,0.7,0,dstImage,CV_8UC3);


/************將圖變成Y'CrCb顏色空間************/
Mat yuv = Mat(smallSize,CV_8UC3);
cvtColor(smallImg,yuv,CV_BGR2YCrCb);
imshow("yuvImg",yuv);
int sw = smallSize.width;
int sh = smallSize.height;
Mat maskPlusBorder;
maskPlusBorder = Mat::zeros(sh+2,sw+2,CV_8UC1);
mask = maskPlusBorder(Rect(1,1,sw,sh));
resize(edges,mask,smallSize);
const int EDGES_THRESHOLD = 80;
threshold(mask,mask,EDGES_THRESHOLD,155,THRESH_BINARY);
dilate(mask,mask,Mat());
erode(mask,mask,Mat());
/*在鼻子前額選擇6個點進行漫水填充***********/
int const NUM_SKIN_POINTS = 6;
Point skinPts[NUM_SKIN_POINTS];
skinPts[0] = Point(sw/2,      sh/2-sh/6);
skinPts[1] = Point(sw/2-sw/11,sh/2-sh/6);
skinPts[2] = Point(sw/2+sw/11,sh/2-sh/6);
skinPts[3] = Point(sw/2,      sh/2+sh/16);
skinPts[4] = Point(sw/2-sw/9, sh/2+sh/16);
skinPts[5] = Point(sw/2+sw/9, sh/2+sh/16);
const int LOWER_Y = 60;
const int UPPER_Y = 80;
const int LOWER_Cr = 25;
const int UPPER_Cr = 15;
const int LOWER_Cb = 20;
const int UPPER_Cb = 15;
Scalar lowerDiff = Scalar(LOWER_Y,LOWER_Cr,LOWER_Cb);
Scalar upperDiff = Scalar(UPPER_Y,UPPER_Cr,UPPER_Cb);

const int CONNECTED_COMPONETS = 4;
const int flags = CONNECTED_COMPONETS|FLOODFILL_FIXED_RANGE|FLOODFILL_MASK_ONLY;
Mat edgeMask = mask.clone();
for(int i = 0;i<NUM_SKIN_POINTS;i++){
floodFill(yuv,maskPlusBorder,skinPts[i],Scalar(),NULL,lowerDiff,upperDiff,flags);
}


Mat BGRImage;
cvtColor(yuv,BGRImage,CV_YCrCb2BGR);
mask -= edgeMask;
int Red = 0;
int Green = 70;
int Blue = 0;
Scalar color2 = CV_RGB(Red,Green,Blue);
add(BGRImage,color2,BGRImage,mask);
resize(BGRImage,BGRImage,size);
add(BGRImage,dstImage,dstImage);
}

////"main.cpp"

#include<opencv2/opencv.hpp>
#include<iostream>
#include"cartoon.h"
using namespace std;
using namespace cv;
int main()
{
int cameraNumber = 0;
VideoCapture camera;
camera.open(cameraNumber);
if(!camera.isOpened()){
cout<<"ERROR!Could not access the camera or video!"<<endl;
exit(1);
}
camera.set(CV_CAP_PROP_FRAME_WIDTH,640);
camera.set(CV_CAP_PROP_FRAME_HEIGHT,480);
while(true){
Mat frame;
camera>>frame;
if(frame.empty()){
cout<<"ERROR!Could not grab a camera frame!"<<endl;
exit(0);
}
Mat displayFrame(frame.size(),CV_8UC3);
cartoonifyImage(frame,displayFrame);
imshow("Cartoonifier",displayFrame);
char keypress = waitKey(10);
if(keypress==27){
break;
}
}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章