《使用OpenCV开发机器视觉项目》&之一卡通画与皮肤变色之初探

     每过几天就去看看OpenCV.org的更新,今天突然发现了一个有趣的东西。http://opencv.org/mastering-opencv-with-practical-computer-vision-projects.html。弄OpenCV的人出版了一个Mastering OpenCV with Practical Computer Vision Projects的书,也就是用OpenCV开发的一切有意思的项目。

 

使用OpenCV开发机器视觉项目

 有以下9个章节

Chapters:

  • Ch1) Cartoonifier and Skin Changer for Android, by Shervin Emami.
  • Ch2) Marker-based Augmented Reality on iPhone or iPad, by Khvedchenia Ievgen.
  • Ch3) Marker-less Augmented Reality, by Khvedchenia Ievgen.
  • Ch4) Exploring Structure from Motion using OpenCV, by Roy Shilkrot.
  • Ch5) Number Plate Recognition using SVM and Neural Networks, by David Escrivá.
  • Ch6) Non-rigid Face Tracking, by Jason Saragih.
  • Ch7) 3D Head Pose Estimation using AAM and POSIT, by Daniel Lélis Baggio.
  • Ch8) Face Recognition using Eigenfaces or Fisherfaces, by Shervin Emami.
  • Ch9) Developing Fluid Wall using the Microsoft Kinect, by Naureen Mahmood.
  • Per-chapter Requirements:

    • Ch1: webcam (for desktop app), or Android development system (for Android app).
    • Ch2: iOS development system (to build an iOS app).
    • Ch3: OpenGL built into OpenCV.
    • Ch4: PCL (http://pointclouds.org/) and SSBA (http://www.inf.ethz.ch/personal/chzach/opensource.html).
    • Ch5: nothing.
    • Ch6: nothing, but requires training data for execution.
    • Ch7: nothing.
    • Ch8: webcam.
    • Ch9: Kinect depth sensor.

Screenshots:

  • Ch1) Cartoonifier and Skin Changer for Android: Ch1) Cartoonifier and Skin Changer for Android
  • Ch2) Marker-based Augmented Reality on iPhone or iPad: Ch2) Marker-based Augmented Reality on iPhone or iPad
  • Ch3) Marker-less Augmented Reality: Ch3) Marker-less Augmented Reality
  • Ch4) Exploring Structure from Motion using OpenCV: Ch4) Exploring Structure from Motion using OpenCV
  • Ch5) Number Plate Recognition using SVM and Neural Networks: Ch5) Number Plate Recognition using SVM and Neural Networks
  • Ch6) Non-rigid Face Tracking: Ch6) Non-rigid Face Tracking
  • Ch7) 3D Head Pose Estimation using AAM and POSIT: Ch7) 3D Head Pose Estimation using AAM and POSIT
  • Ch8) Face Recognition using Eigenfaces or Fisherfaces: Ch8) Face Recognition using Eigenfaces or Fisherfaces
  • Ch9) Developing Fluid Wall using the Microsoft Kinect: Ch9) Developing Fluid Wall using the Microsoft Kinect

     看看,他们确实涵盖了当今最热门的一些机器视觉相关项目,其中包括我喜欢的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


这些项目有趣,并且十分实用,很可能进而在其基础上开发更多十分有趣的项目。希望更多的人来研读这些代码,并作分享。

你可能感兴趣的:(MFC/C++,OpenCV)