每过几天就去看看OpenCV.org的更新,今天突然发现了一个有趣的东西。http://opencv.org/mastering-opencv-with-practical-computer-vision-projects.html。弄OpenCV的人出版了一个Mastering OpenCV with Practical Computer Vision Projects的书,也就是用OpenCV开发的一切有意思的项目。
使用OpenCV开发机器视觉项目
有以下9个章节
Per-chapter Requirements:
看看,他们确实涵盖了当今最热门的一些机器视觉相关项目,其中包括我喜欢的Kinect,甚至我熟悉的人脸识别、人脸跟踪、人脸朝向估计等等(这么多关于人脸的!),还包括虚拟现实之类技术,有时间也得看看。这本书可以买纸质版也可以买电子版,购买地址 PacktPub。好吧,估计一般人是买不到的,国外的书果然不便宜,$44.99
不过书中配套的项目源码倒是都有的!https://github.com/MasteringOpenCV/code
第一个项目:卡通画和肤色变化初探
我在windows上尝试编译了第一个例子(他既有android平台的代码也给出了PC平台的)。以下是截图:
第一张和第四张图片都是卡通图,第2张是evil状态的,所以有点惨不忍睹吧,第三张是素描。具体算法我还未去细读,给出下载第一个项目的VS2010地址。通过debug可以编译出可用的exe,而release尽然无法检测到摄像头以致exe无法运行,编译时注意。
给出主要的卡通画函数实现代码:
/*****************************************************************************
* cartoon.cpp
* Create a cartoon-like or painting-like image filter.
******************************************************************************
* by Shervin Emami, 5th Dec 2012 ([email protected])
* http://www.shervinemami.info/
******************************************************************************
* Ch1 of the book "Mastering OpenCV with Practical Computer Vision Projects"
* Copyright Packt Publishing 2012.
* http://www.packtpub.com/cool-projects-with-opencv/book
*****************************************************************************/
#include "cartoon.h"
#include "ImageUtils.h" // Handy functions for debugging OpenCV images, by Shervin Emami.
// Convert the given photo into a cartoon-like or painting-like image.
// Set sketchMode to true if you want a line drawing instead of a painting.
// Set alienMode to true if you want alien skin instead of human.
// Set evilMode to true if you want an "evil" character instead of a "good" character.
// Set debugType to 1 to show where skin color is taken from, and 2 to show the skin mask in a new window (for desktop).
void cartoonifyImage(Mat srcColor, Mat dst, bool sketchMode, bool alienMode, bool evilMode, int debugType)
{
// Convert from BGR color to Grayscale
Mat srcGray;
cvtColor(srcColor, srcGray, CV_BGR2GRAY);
// Remove the pixel noise with a good Median filter, before we start detecting edges.
medianBlur(srcGray, srcGray, 7);
Size size = srcColor.size();
Mat mask = Mat(size, CV_8U);
Mat edges = Mat(size, CV_8U);
if (!evilMode) {
// Generate a nice edge mask, similar to a pencil line drawing.
Laplacian(srcGray, edges, CV_8U, 5);
threshold(edges, mask, 80, 255, THRESH_BINARY_INV);
// Mobile cameras usually have lots of noise, so remove small
// dots of black noise from the black & white edge mask.
removePepperNoise(mask);
}
else {
// Evil mode, making everything look like a scary bad guy.
// (Where "srcGray" is the original grayscale image plus a medianBlur of size 7x7).
Mat edges2;
Scharr(srcGray, edges, CV_8U, 1, 0);
Scharr(srcGray, edges2, CV_8U, 1, 0, -1);
edges += edges2;
threshold(edges, mask, 12, 255, THRESH_BINARY_INV);
medianBlur(mask, mask, 3);
}
//imshow("edges", edges);
//imshow("mask", mask);
// For sketch mode, we just need the mask!
if (sketchMode) {
// The output image has 3 channels, not a single channel.
cvtColor(mask, dst, CV_GRAY2BGR);
return;
}
// Do the bilateral filtering at a shrunken scale, since it
// runs so slowly but doesn't need full resolution for a good effect.
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);
// Perform many iterations of weak bilateral filtering, to enhance the edges
// while blurring the flat regions, like a cartoon.
Mat tmp = Mat(smallSize, CV_8UC3);
int repetitions = 7; // Repetitions for strong cartoon effect.
for (int i=0; i= 1)
circle(smallImgBGR, skinPts[i], 5, CV_RGB(0, 0, 255), 1, CV_AA);
}
if (debugType >= 2)
imshow("flood mask", mask*120); // Draw the edges as white and the skin region as grey.
// After the flood fill, "mask" contains both edges and skin pixels, whereas
// "edgeMask" just contains edges. So to get just the skin pixels, we can remove the edges from it.
mask -= edgeMask;
// "mask" now just contains 1's in the skin pixels and 0's for non-skin pixels.
// Change the color of the skin pixels in the given BGR image.
int Red = 0;
int Green = 70;
int Blue = 0;
add(smallImgBGR, Scalar(Blue, Green, Red), smallImgBGR, mask);
}
// Remove black dots (upto 4x4 in size) of noise from a pure black & white image.
// ie: The input image should be mostly white (255) and just contains some black (0) noise
// in addition to the black (0) edges.
void removePepperNoise(Mat &mask)
{
// For simplicity, ignore the top & bottom row border.
for (int y=2; y
这些项目有趣,并且十分实用,很可能进而在其基础上开发更多十分有趣的项目。希望更多的人来研读这些代码,并作分享。