深入理解OpenCV第一章

Android系统上生成卡通画

 

不知道为什么外星人那块的函数运行到floodfill的时候一直不出结果……其他部分都很正常orz

/* main.cpp */
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
#include "cartoon.h"

using namespace std;
using namespace cv;

int main(int argc, char** argv)
{
	
	//加载图像
	int cameraNumber = 0;
	if (argc > 1){
		cameraNumber = atoi(argv[1]);
	}
	//Get access to the camera
	VideoCapture camera;
	camera.open(cameraNumber);
	if (!camera.isOpened()){
		cerr << "ERROR : Could not access the camera or video!" << endl;
		exit(1);
	}

	//Try to set the camera resolution
	camera.set(CV_CAP_PROP_FRAME_WIDTH, 640);
	camera.set(CV_CAP_PROP_FRAME_HEIGHT, 480);


	while (true){
		//Grab the next camera frame.
		Mat cameraFrame;
		camera >> cameraFrame;
		if (cameraFrame.empty()){
			cerr << "ERROR : Could not grab a camera frame!" << endl;
			exit(1);
		}

		//Create a blank output image,that we will draw onto.
		Mat displayedFrame(cameraFrame.size(), CV_8UC3);

		//Run the cartoonfier filter on the camera frame.
		//cartoonifyImage(cameraFrame, displayedFrame);//

		//evilImage
		evilImage(cameraFrame, displayedFrame);

		//draw a face position
		//facePosition(cameraFrame, displayedFrame);

		//elienImage
		//elienImage(cameraFrame, displayedFrame);

		//Display the processed image onto the screen.
		imshow("Cartoonifier", displayedFrame);

		//IMPORTANT ; Wait for at least 20 milliseconds
		//so that the image can be displayed on the screen!
		//Also checks if a key was pressed in the GUI window.
		//Note that it should be a "char" to support Linux.
		char keypress = cv::waitKey(20); //Need this to see anything!
		if (keypress == 27){//Escape Key

			//Quit the program!
			break;
		}

	}//end while
	
	return 0;
}

/* cartoon.cpp */

#include "cartoon.h"


cartoon::cartoon()
{
}


cartoon::~cartoon()
{
}

void cartoonifyImage(Mat& srcColor,Mat& dst){
	
	//素描图像
	Mat gray;
	cvtColor(srcColor, gray, CV_BGR2GRAY);
	const int MEDIAN_BLUR_FILTER_SIZE = 7;
	medianBlur(gray, gray, MEDIAN_BLUR_FILTER_SIZE);
	Mat edges;
	const int LAPLACIAN_FILTER_SIZE = 5;
	Laplacian(gray, edges, CV_8U, LAPLACIAN_FILTER_SIZE);
	//二值化阈值
	Mat mask;
	const int EDGES_THRESHOLD = 80;
	threshold(edges, mask, EDGES_THRESHOLD, 255, THRESH_BINARY_INV);

	//卡通画
	Size size = srcColor.size();
	Size smallSize;
	smallSize.width = size.width / 2;
	smallSize.height = size.height / 2;
	Mat smallImg = Mat(smallSize, CV_8UC3);
	resize(srcColor, smallImg, smallSize, 0, 0, INTER_LINEAR);
	//双边滤波
	Mat tmp = Mat(smallSize, CV_8UC3);
	int repetitions = 7;//Repetitions for strong cartoon effect.
	for (int i = 0; i < repetitions; i++){
		int ksize = 9;   //Filter size.Has a large effect on speed.
		double sigmaColor = 9;  //Filter color strength.
		double sigmaSpace = 7;  //Spatial strength.Affects speed.
		bilateralFilter(smallImg, tmp, ksize, sigmaColor, sigmaSpace);
		bilateralFilter(tmp, smallImg, ksize, sigmaColor, sigmaSpace);
	}
	//图像复原
	Mat bigImg;
	resize(smallImg, bigImg, size, 0, 0, INTER_LINEAR);
	//Mat dst;
	dst.setTo(0);
	bigImg.copyTo(dst, mask);

	
}

void evilImage(Mat& srcColor, Mat& dst){
	Mat srcGray;
	cvtColor(srcColor, srcGray, CV_BGR2GRAY);
	const int MEDIAN_BLUR_FILTER_SIZE = 7;
	medianBlur(srcGray, srcGray, MEDIAN_BLUR_FILTER_SIZE);
	Mat edges1, edges2;
	Scharr(srcGray, edges1, CV_8U, 1, 0);
	Scharr(srcGray, edges2, CV_8U, 1, 0, -1);
	edges1 += edges2;  //Combine the x&y edges together.
	const int EVIL_EDGE_THRESHOLD = 12;
	Mat mask1;
	threshold(edges1, mask1, EVIL_EDGE_THRESHOLD, 255, THRESH_BINARY_INV);
	medianBlur(mask1, mask1, 3);

	//Mat dst1;
	dst.setTo(0);
	srcColor.copyTo(dst, mask1);
	
}

void facePosition(Mat& srcColor, Mat& dst){
	Size size = srcColor.size();

	//Draw the color face onto a black background.
	Mat faceOutline = Mat::zeros(size, CV_8UC3);
	Scalar color = CV_RGB(255, 255, 0); //Yellow
	int thickness = 4;
	//Use 70% of the screen height as the face height.
	int sw = size.width;
	int sh = size.height;
	int faceH = sh / 2 * 70 / 100;  //"faceH" is the radius of the ellipse.
	//Scale the width to be the same shape for any screen width.
	int faceW = faceH * 72 / 100;
	//Draw the face outline.
	ellipse(faceOutline, Point(sw / 2, sh / 2), Size(faceW, faceH), 0, 0, 360, color, thickness, CV_AA);


	//Draw the eye outlines,as 2 arcs per eye.
	int eyeW = faceW * 23 / 100;
	int eyeH = faceW * 11 / 100;
	int eyeX = faceW * 48 / 100;
	int eyeY = faceW * 13 / 100;
	Size eyeSize = Size(eyeW, eyeH);
	//Set the angle and shift for the eye half ellipses.
	int eyeA = 15;//angle in degrees.
	int eyeYshift = 11;
	//Draw the top of the right eye.
	ellipse(faceOutline, Point(sw / 2 - eyeX, sh / 2 - eyeY), eyeSize, 0, 180 + eyeA, 360 - eyeA, color, thickness, CV_AA);
	//Draw the bottom of the right eye.
	ellipse(faceOutline, Point(sw / 2 - eyeX, sh / 2 - eyeY - eyeYshift), eyeSize, 0, 0 + eyeA, 180 - eyeA, color, thickness, CV_AA);
	//Draw the top of the left eye.
	ellipse(faceOutline, Point(sw / 2 + eyeX, sh / 2 - eyeY), eyeSize, 0, 180 + eyeA, 360 - eyeA, color, thickness, CV_AA);
	//Draw the bottom of the left eye.
	ellipse(faceOutline, Point(sw / 2 + eyeX, sh / 2 - eyeY - eyeYshift), eyeSize, 0, 0 + eyeA, 180 - eyeA, color, thickness, CV_AA);

	//Draw the bottom lip of the mouth.
	int mouthY = faceH * 48 / 100;
	int mouthW = faceH * 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);

	//Draw anti-aliased text.
	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(srcColor, 1.0, faceOutline, 0.7, 0, dst, CV_8UC3);
}

void elienImage(Mat& srcColor, Mat& dst){

	
	//素描图像
	Mat gray;
	cvtColor(srcColor, gray, CV_BGR2GRAY);
	const int MEDIAN_BLUR_FILTER_SIZE = 7;
	medianBlur(gray, gray, MEDIAN_BLUR_FILTER_SIZE);
	Mat edges;
	const int LAPLACIAN_FILTER_SIZE = 5;
	Laplacian(gray, edges, CV_8U, LAPLACIAN_FILTER_SIZE);
	
	//缩小图像
	Size size = srcColor.size();
	Size smallSize;
	smallSize.width = size.width / 2;
	smallSize.height = size.height / 2;
	Mat smallImg = Mat(smallSize, CV_8UC3);
	resize(srcColor, smallImg, smallSize, 0, 0, INTER_LINEAR);
	//彩图转成YUV格式
	Mat yuv = Mat(smallSize, CV_8UC3);
	cvtColor(smallImg, yuv, CV_BGR2YCrCb);
	//dst = yuv;
	
	int sw = smallSize.width;
	int sh = smallSize.height;
	Mat mask, maskPlusBorder;
	maskPlusBorder = Mat::zeros(sh + 2, sw + 2, CV_8UC1);
	mask = maskPlusBorder(Rect(1, 1, sw, sh));//mask is in maskPlusBorder.
	resize(edges, mask, smallSize);//put edges in both of them.

	//dst = maskPlusBorder;

	
	//二值化阈值
	const int EDGES_THRESHOLD = 80;
	threshold(mask, mask, EDGES_THRESHOLD, 255, THRESH_BINARY);
	dilate(mask, mask, Mat());
	erode(mask, mask, Mat());

	
	//在鼻子,脸颊和前额选择六个点,这些点的位置依赖于早期所确定的面部轮廓
	//sw = size.width;
	//sh = size.height;
	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_COMPONENTS = 8;//To fill diagonally,use 8.
	const int flags = CONNECTED_COMPONENTS | FLOODFILL_FIXED_RANGE | FLOODFILL_MASK_ONLY;
	Mat edgeMask = mask.clone();//Keep a copy of the edge mask;
	//"maskPlusBorder" is initialized with edges to block floodFill().
	//imshow("test", mask);
	for (int i = 0; i < NUM_SKIN_POINTS; i++){
		floodFill(yuv, maskPlusBorder, skinPts[i], Scalar(), NULL, lowerDiff, upperDiff, flags);
		//搞不出来,就是难受,非常难受TAT
	}

	dst = yuv;
	
	

}
/* cartoon.h */
#pragma once
//Include OpenCV's C++ Interface
#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;
class cartoon
{
public:
	cartoon();
	~cartoon();
	
};

void cartoonifyImage(Mat& srcColor,Mat& dst);
void evilImage(Mat& srcColor, Mat& dst);
void facePosition(Mat& srcColor, Mat& dst);
void elienImage(Mat& srcColor, Mat& dst);

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值