├── Chapter01 ├── CMakeLists.txt ├── README.txt ├── loadDisplaySave.cpp ├── logo.cpp └── mat.cpp ├── Chapter02 ├── CMakeLists.txt ├── README.txt ├── addImages.cpp ├── colorReduce.cpp ├── contrast.cpp ├── remapping.cpp └── saltImage.cpp ├── Chapter03 ├── CMakeLists.txt ├── README.txt ├── colorDetectController.h ├── colorDetection.cpp ├── colordetector.cpp ├── colordetector.h ├── controller.cpp └── huesaturation.cpp ├── Chapter04 ├── CMakeLists.txt ├── README.txt ├── colorhistogram.h ├── contentFinder.cpp ├── contentFinder.h ├── finder.cpp ├── histogram.h ├── histograms.cpp ├── imageComparator.h ├── integral.cpp ├── integral.h ├── retrieve.cpp └── tracking.cpp ├── Chapter05 ├── CMakeLists.txt ├── README.txt ├── morpho2.cpp ├── morphoFeatures.h ├── morphology.cpp ├── mserFeatures.cpp ├── mserFeatures.h ├── segment.cpp └── watershedSegmentation.h ├── Chapter06 ├── CMakeLists.txt ├── README.txt ├── derivatives.cpp ├── filters.cpp └── laplacianZC.h ├── Chapter07 ├── CMakeLists.txt ├── README.txt ├── blobs.cpp ├── contours.cpp ├── edgedetector.h └── linefinder.h ├── Chapter08 ├── CMakeLists.txt ├── README.txt ├── harrisDetector.h └── interestPoints.cpp ├── Chapter09 ├── CMakeLists.txt ├── README.txt ├── binaryDescriptors.cpp ├── matcher.cpp └── patches.cpp ├── Chapter10 ├── CMakeLists.txt ├── CameraCalibrator.cpp ├── CameraCalibrator.h ├── README.txt ├── calibrate.cpp ├── estimateF.cpp ├── estimateH.cpp ├── matchingTarget.cpp ├── robustMatcher.h ├── robustmatching.cpp └── targetMatcher.h ├── Chapter11 ├── BGFGSegmentor.h ├── CMakeLists.txt ├── README.txt ├── featuretracker.h ├── foreground.cpp ├── tracking.cpp ├── videoprocessing.cpp └── videoprocessor.h └── README /Chapter01/CMakeLists.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laganiere/OpenCV2Cookbook2ndEd/986f6e92f561b7d7871b063aab7e3e91ed9d6ea8/Chapter01/CMakeLists.txt -------------------------------------------------------------------------------- /Chapter01/README.txt: -------------------------------------------------------------------------------- 1 | This directory contains material supporting Chapter 1 of the cookbook: 2 | Computer Vision Programming using the OpenCV Library. 3 | Second Edition 4 | by Robert Laganiere, Packt Publishing, 2013. 5 | 6 | 7 | File: 8 | loadDisplaySave.cpp 9 | corresponds to Recipe: 10 | Loading, displaying and saving images 11 | 12 | File: 13 | mat.cpp 14 | corresponds to Recipe: 15 | Exploring the cv::Mat data structure 16 | 17 | File: 18 | logo.cpp 19 | corresponds to Recipe: 20 | Defining region of interest -------------------------------------------------------------------------------- /Chapter01/loadDisplaySave.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 1 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | 24 | void onMouse( int event, int x, int y, int flags, void* param) { 25 | 26 | cv::Mat *im= reinterpret_cast(param); 27 | 28 | switch (event) { // dispatch the event 29 | 30 | case CV_EVENT_LBUTTONDOWN: // mouse button down event 31 | 32 | // display pixel value at (x,y) 33 | std::cout << "at (" << x << "," << y << ") value is: " 34 | << static_cast(im->at(cv::Point(x,y))) << std::endl; 35 | break; 36 | } 37 | } 38 | 39 | int main() { 40 | 41 | cv::Mat image; // create an empty image 42 | std::cout << "This image is " << image.rows << " x " 43 | << image.cols << std::endl; 44 | 45 | // read the input image as a gray-scale image 46 | image= cv::imread("puppy.bmp", CV_LOAD_IMAGE_GRAYSCALE); 47 | 48 | if (image.empty()) { // error handling 49 | // no image has been created... 50 | // possibly display an error message 51 | // and quit the application 52 | std::cout << "Error reading image..." << std::endl; 53 | return 0; 54 | } 55 | 56 | std::cout << "This image is " << image.rows << " x " 57 | << image.cols << std::endl; 58 | std::cout << "This image has " 59 | << image.channels() << " channel(s)" << std::endl; 60 | 61 | // create image window named "My Image" 62 | cv::namedWindow("Original Image"); // define the window (optional) 63 | cv::imshow("Original Image", image); // show the image 64 | 65 | // set the mouse callback for this image 66 | cv::setMouseCallback("Original Image", onMouse, reinterpret_cast(&image)); 67 | 68 | cv::Mat result; // we create another empty image 69 | cv::flip(image,result,1); // positive for horizontal 70 | // 0 for vertical, 71 | // negative for both 72 | 73 | cv::namedWindow("Output Image"); // the output window 74 | cv::imshow("Output Image", result); 75 | 76 | cv::waitKey(0); // 0 to indefinitely wait for a key pressed 77 | // specifying a positive value will wait for 78 | // the given amount of msec 79 | 80 | cv::imwrite("output.bmp", result); // save result 81 | 82 | // create another image window named 83 | cv::namedWindow("Drawing on an Image"); // define the window 84 | 85 | cv::circle(image, // destination image 86 | cv::Point(155,110), // center coordinate 87 | 65, // radius 88 | 0, // color (here black) 89 | 3); // thickness 90 | 91 | cv::putText(image, // destination image 92 | "This is a dog.", // text 93 | cv::Point(40,200), // text position 94 | cv::FONT_HERSHEY_PLAIN, // font type 95 | 2.0, // font scale 96 | 255, // text color (here white) 97 | 2); // text thickness 98 | 99 | cv::imshow("Drawing on an Image", image); // show the image 100 | 101 | cv::waitKey(0); // 0 to indefinitely wait for a key pressed 102 | 103 | return 0; 104 | } 105 | 106 | -------------------------------------------------------------------------------- /Chapter01/logo.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 1 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | 24 | int main() { 25 | 26 | // define an image window 27 | cv::namedWindow("Image"); 28 | 29 | // read the image 30 | cv::Mat image= cv::imread("puppy.bmp"); 31 | 32 | // read the logo 33 | cv::Mat logo= cv::imread("smalllogo.png"); 34 | 35 | // define image ROI at image bottom-right 36 | cv::Mat imageROI(image, 37 | cv::Rect(image.cols-logo.cols, //ROI coordinates 38 | image.rows-logo.rows, 39 | logo.cols,logo.rows));// ROI size 40 | 41 | // insert logo 42 | logo.copyTo(imageROI); 43 | 44 | cv::imshow("Image", image); // show the image 45 | cv::waitKey(0); // wait for a key pressed 46 | 47 | // re-read the original image 48 | image= cv::imread("puppy.bmp"); 49 | 50 | // define image ROI at image bottom-right 51 | imageROI= image(cv::Rect(image.cols-logo.cols,image.rows-logo.rows, 52 | logo.cols,logo.rows)); 53 | // or using ranges: 54 | // imageROI= image(cv::Range(image.rows-logo.rows,image.rows), 55 | // cv::Range(image.cols-logo.cols,image.cols)); 56 | 57 | // use the logo as a mask (must be gray-level) 58 | cv::Mat mask(logo); 59 | 60 | // insert by copying only at locations of non-zero mask 61 | logo.copyTo(imageROI,mask); 62 | 63 | cv::imshow("Image", image); // show the image 64 | cv::waitKey(0); // wait for a key pressed 65 | 66 | return 0; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /Chapter01/mat.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 1 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | 24 | // test function that creates an image 25 | cv::Mat function() { 26 | 27 | // create image 28 | cv::Mat ima(500,500,CV_8U,50); 29 | // return it 30 | return ima; 31 | } 32 | 33 | int main() { 34 | 35 | // define image windows 36 | cv::namedWindow("Image 1"); 37 | cv::namedWindow("Image 2"); 38 | cv::namedWindow("Image 3"); 39 | cv::namedWindow("Image 4"); 40 | cv::namedWindow("Image 5"); 41 | cv::namedWindow("Image"); 42 | 43 | // create a new image made of 240 rows and 320 columns 44 | cv::Mat image1(240,320,CV_8U,100); 45 | // or: 46 | // cv::Mat image1(240,320,CV_8U,cv::Scalar(100)); 47 | 48 | cv::imshow("Image", image1); // show the image 49 | cv::waitKey(0); // wait for a key pressed 50 | 51 | // re-allocate a new image 52 | // (only if size or type are different) 53 | image1.create(200,200,CV_8U); 54 | image1= 200; 55 | 56 | cv::imshow("Image", image1); // show the image 57 | cv::waitKey(0); // wait for a key pressed 58 | 59 | // create a red color image 60 | // channel order is BGR 61 | cv::Mat image2(240,320,CV_8UC3,cv::Scalar(0,0,255)); 62 | 63 | // or: 64 | // cv::Mat image2(cv::Size(320,240),CV_8UC3); 65 | // image2= cv::Scalar(0,0,255); 66 | 67 | cv::imshow("Image", image2); // show the image 68 | cv::waitKey(0); // wait for a key pressed 69 | 70 | // read an image 71 | cv::Mat image3= cv::imread("puppy.bmp"); 72 | 73 | // all these images point to the same data block 74 | cv::Mat image4(image3); 75 | image1= image3; 76 | 77 | // these images are new copies of the source image 78 | image3.copyTo(image2); 79 | cv::Mat image5= image3.clone(); 80 | 81 | // transform the image for testing 82 | cv::flip(image3,image3,1); 83 | 84 | // check which images have been affected by the processing 85 | cv::imshow("Image 3", image3); 86 | cv::imshow("Image 1", image1); 87 | cv::imshow("Image 2", image2); 88 | cv::imshow("Image 4", image4); 89 | cv::imshow("Image 5", image5); 90 | cv::waitKey(0); // wait for a key pressed 91 | 92 | // get a gray-level image from a function 93 | cv::Mat gray= function(); 94 | 95 | cv::imshow("Image", gray); // show the image 96 | cv::waitKey(0); // wait for a key pressed 97 | 98 | // read the image in gray scale 99 | image1= cv::imread("puppy.bmp", CV_LOAD_IMAGE_GRAYSCALE); 100 | 101 | // convert the image into a floating point image [0,1] 102 | image1.convertTo(image2,CV_32F,1/255.0,0.0); 103 | 104 | cv::imshow("Image", image2); // show the image 105 | cv::waitKey(0); // wait for a key pressed 106 | 107 | return 0; 108 | } 109 | 110 | -------------------------------------------------------------------------------- /Chapter02/CMakeLists.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laganiere/OpenCV2Cookbook2ndEd/986f6e92f561b7d7871b063aab7e3e91ed9d6ea8/Chapter02/CMakeLists.txt -------------------------------------------------------------------------------- /Chapter02/README.txt: -------------------------------------------------------------------------------- 1 | This directory contains material supporting chapter 2 of the cookbook: 2 | Computer Vision Programming using the OpenCV Library. 3 | Second Edition 4 | by Robert Laganiere, Packt Publishing, 2013. 5 | 6 | File: 7 | saltImage.cpp 8 | correspond to Recipe: 9 | Accessing the pixel values 10 | 11 | File: 12 | colorReduce.cpp 13 | correspond to Recipes: 14 | Scanning an image with pointers 15 | Scanning an image with iterators 16 | Writing efficient image scanning loops 17 | 18 | File: 19 | contrast.cpp 20 | correspond to Recipe: 21 | Scanning an image with neighbour access 22 | 23 | File: 24 | addImages.cpp 25 | correspond to Recipes: 26 | Performing simple image arithmetic 27 | 28 | File: 29 | remapping.cpp 30 | correspond to Recipes: 31 | Remapping an image 32 | 33 | You need the images: 34 | boldt.jpg 35 | image.jpg (any image will do) 36 | rain.jpg -------------------------------------------------------------------------------- /Chapter02/addImages.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 2 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | int main() 26 | { 27 | cv::Mat image1; 28 | cv::Mat image2; 29 | 30 | image1= cv::imread("boldt.jpg"); 31 | image2= cv::imread("rain.jpg"); 32 | if (!image1.data) 33 | return 0; 34 | if (!image2.data) 35 | return 0; 36 | 37 | // images ares resize for book printing 38 | cv::resize(image1, image1, cv::Size(), 0.6, 0.6); 39 | cv::resize(image2, image2, cv::Size(), 0.6, 0.6); 40 | 41 | cv::namedWindow("Image 1"); 42 | cv::imshow("Image 1",image1); 43 | cv::namedWindow("Image 2"); 44 | cv::imshow("Image 2",image2); 45 | 46 | cv::Mat result; 47 | // add two images 48 | cv::addWeighted(image1,0.7,image2,0.9,0.,result); 49 | 50 | cv::namedWindow("result"); 51 | cv::imshow("result",result); 52 | 53 | // using overloaded operator 54 | result= 0.7*image1+0.9*image2; 55 | 56 | cv::namedWindow("result with operators"); 57 | cv::imshow("result with operators",result); 58 | 59 | image2= cv::imread("rain.jpg",0); 60 | // images ares resize for book printing 61 | cv::resize(image2, image2, cv::Size(), 0.6, 0.6); 62 | 63 | // create vector of 3 images 64 | std::vector planes; 65 | // split 1 3-channel image into 3 1-channel images 66 | cv::split(image1,planes); 67 | // add to blue channel 68 | planes[0]+= image2; 69 | // merge the 3 1-channel images into 1 3-channel image 70 | cv::merge(planes,result); 71 | 72 | cv::namedWindow("Result on blue channel"); 73 | cv::imshow("Result on blue channel",result); 74 | 75 | cv::waitKey(); 76 | 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /Chapter02/contrast.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 2 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | 26 | void sharpen(const cv::Mat &image, cv::Mat &result) { 27 | 28 | result.create(image.size(), image.type()); // allocate if necessary 29 | int nchannels= image.channels(); 30 | 31 | for (int j= 1; j(j-1); // previous row 34 | const uchar* current= image.ptr(j); // current row 35 | const uchar* next= image.ptr(j+1); // next row 36 | 37 | uchar* output= result.ptr(j); // output row 38 | 39 | for (int i=nchannels; i<(image.cols-1)*nchannels; i++) { 40 | 41 | *output++= cv::saturate_cast(5*current[i]-current[i-nchannels]-current[i+nchannels]-previous[i]-next[i]); 42 | // output[i]= cv::saturate_cast(5*current[i]-current[i-nchannels]-current[i+nchannels]-previous[i]-next[i]); 43 | } 44 | } 45 | 46 | // Set the unprocess pixels to 0 47 | result.row(0).setTo(cv::Scalar(0)); 48 | result.row(result.rows-1).setTo(cv::Scalar(0)); 49 | result.col(0).setTo(cv::Scalar(0)); 50 | result.col(result.cols-1).setTo(cv::Scalar(0)); 51 | } 52 | 53 | // same function but using iterator 54 | // this one works only for gray-level image 55 | void sharpenIterator(const cv::Mat &image, cv::Mat &result) { 56 | 57 | cv::Mat_::const_iterator it= image.begin()+image.cols; 58 | cv::Mat_::const_iterator itend= image.end()-image.cols; 59 | cv::Mat_::const_iterator itup= image.begin(); 60 | cv::Mat_::const_iterator itdown= image.begin()+2*image.cols; 61 | 62 | result.create(image.size(), image.type()); // allocate if necessary 63 | cv::Mat_::iterator itout= result.begin()+result.cols; 64 | 65 | for ( ; it!= itend; ++it, ++itout, ++itup, ++itdown) { 66 | 67 | *itout= cv::saturate_cast(*it *5 - *(it-1)- *(it+1)- *itup - *itdown); 68 | } 69 | 70 | // Set the unprocess pixels to 0 71 | result.row(0).setTo(cv::Scalar(0)); 72 | result.row(result.rows-1).setTo(cv::Scalar(0)); 73 | result.col(0).setTo(cv::Scalar(0)); 74 | result.col(result.cols-1).setTo(cv::Scalar(0)); 75 | } 76 | 77 | void sharpen2D(const cv::Mat &image, cv::Mat &result) { 78 | 79 | // Construct kernel (all entries initialized to 0) 80 | cv::Mat kernel(3,3,CV_32F,cv::Scalar(0)); 81 | // assigns kernel values 82 | kernel.at(1,1)= 5.0; 83 | kernel.at(0,1)= -1.0; 84 | kernel.at(2,1)= -1.0; 85 | kernel.at(1,0)= -1.0; 86 | kernel.at(1,2)= -1.0; 87 | 88 | //filter the image 89 | cv::filter2D(image,result,image.depth(),kernel); 90 | } 91 | 92 | int main() 93 | { 94 | cv::Mat image= cv::imread("boldt.jpg"); 95 | if (!image.data) 96 | return 0; 97 | // image is resize for book printing 98 | cv::resize(image, image, cv::Size(), 0.6, 0.6); 99 | 100 | cv::Mat result; 101 | 102 | double time= static_cast(cv::getTickCount()); 103 | sharpen(image, result); 104 | time= (static_cast(cv::getTickCount())-time)/cv::getTickFrequency(); 105 | std::cout << "time= " << time << std::endl; 106 | 107 | cv::namedWindow("Image"); 108 | cv::imshow("Image",result); 109 | 110 | // open the image in gray-level 111 | image= cv::imread("boldt.jpg",0); 112 | // image is resize for book printing 113 | cv::resize(image, image, cv::Size(), 0.6, 0.6); 114 | 115 | time = static_cast(cv::getTickCount()); 116 | sharpenIterator(image, result); 117 | time= (static_cast(cv::getTickCount())-time)/cv::getTickFrequency(); 118 | std::cout << "time 3= " << time << std::endl; 119 | 120 | cv::namedWindow("Sharpened Image"); 121 | cv::imshow("Sharpened Image",result); 122 | 123 | image= cv::imread("boldt.jpg"); 124 | // image is resize for book printing 125 | cv::resize(image, image, cv::Size(), 0.6, 0.6); 126 | 127 | time = static_cast(cv::getTickCount()); 128 | sharpen2D(image, result); 129 | time= (static_cast(cv::getTickCount())-time)/cv::getTickFrequency(); 130 | std::cout << "time 2D= " << time << std::endl; 131 | 132 | cv::namedWindow("Image 2D"); 133 | cv::imshow("Image 2D",result); 134 | 135 | cv::waitKey(); 136 | 137 | return 0; 138 | } 139 | 140 | 141 | -------------------------------------------------------------------------------- /Chapter02/remapping.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 2 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | // remapping an image by creating wave effects 26 | void wave(const cv::Mat &image, cv::Mat &result) { 27 | 28 | // the map functions 29 | cv::Mat srcX(image.rows,image.cols,CV_32F); // x-map 30 | cv::Mat srcY(image.rows,image.cols,CV_32F); // y-map 31 | 32 | // creating the mapping 33 | for (int i=0; i(i,j)= j; 37 | srcY.at(i,j)= i+3*sin(j/6.0); 38 | 39 | // horizontal flipping 40 | // srcX.at(i,j)= image.cols-j-1; 41 | // srcY.at(i,j)= i; 42 | } 43 | } 44 | 45 | // applying the mapping 46 | cv::remap(image, // source image 47 | result, // destination image 48 | srcX, // x map 49 | srcY, // y map 50 | cv::INTER_LINEAR); // interpolation method 51 | } 52 | 53 | int main() 54 | { 55 | cv::Mat image= cv::imread("boldt.jpg",0); 56 | // image is resize for book printing 57 | cv::resize(image, image, cv::Size(), 0.6, 0.6); 58 | 59 | cv::namedWindow("Image"); 60 | cv::imshow("Image",image); 61 | 62 | cv::Mat result; 63 | wave(image,result); 64 | 65 | cv::namedWindow("Remapped image"); 66 | cv::imshow("Remapped image",result); 67 | 68 | cv::waitKey(); 69 | return 0; 70 | } 71 | 72 | 73 | -------------------------------------------------------------------------------- /Chapter02/saltImage.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 2 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include // for std::rand 23 | 24 | void salt(cv::Mat image, int n) { 25 | 26 | int i,j; 27 | for (int k=0; k(j,i)= 255; 37 | 38 | } else if (image.type() == CV_8UC3) { // color image 39 | 40 | image.at(j,i)[0]= 255; 41 | image.at(j,i)[1]= 255; 42 | image.at(j,i)[2]= 255; 43 | } 44 | } 45 | } 46 | 47 | // This is an extra version of the function 48 | // to illustrate the use of cv::Mat_ 49 | // works only for a 1-channel image 50 | void salt2(cv::Mat image, int n) { 51 | 52 | // use image with a Mat_ template 53 | cv::Mat_ im2(image); 54 | 55 | // or with references: 56 | // cv::Mat_& im2= reinterpret_cast&>(image); 57 | 58 | int i,j; 59 | for (int k=0; k 23 | #include "colordetector.h" 24 | 25 | class ColorDetectController { 26 | 27 | private: 28 | 29 | // the algorithm class 30 | ColorDetector *cdetect; 31 | 32 | cv::Mat image; // The image to be processed 33 | cv::Mat result; // The image result 34 | 35 | 36 | public: 37 | ColorDetectController() { // private constructor 38 | 39 | //setting up the application 40 | cdetect= new ColorDetector(); 41 | } 42 | 43 | // Sets the colour distance threshold 44 | void setColorDistanceThreshold(int distance) { 45 | 46 | cdetect->setColorDistanceThreshold(distance); 47 | } 48 | 49 | // Gets the colour distance threshold 50 | int getColorDistanceThreshold() const { 51 | 52 | return cdetect->getColorDistanceThreshold(); 53 | } 54 | 55 | // Sets the colour to be detected 56 | void setTargetColor(unsigned char red, unsigned char green, unsigned char blue) { 57 | 58 | cdetect->setTargetColor(blue,green,red); 59 | } 60 | 61 | // Gets the colour to be detected 62 | void getTargetColour(unsigned char &red, unsigned char &green, unsigned char &blue) const { 63 | 64 | cv::Vec3b colour= cdetect->getTargetColor(); 65 | 66 | red= colour[2]; 67 | green= colour[1]; 68 | blue= colour[0]; 69 | } 70 | 71 | // Sets the input image. Reads it from file. 72 | bool setInputImage(std::string filename) { 73 | 74 | image= cv::imread(filename); 75 | 76 | return !image.empty(); 77 | } 78 | 79 | // Returns the current input image. 80 | const cv::Mat getInputImage() const { 81 | 82 | return image; 83 | } 84 | 85 | // Performs image processing. 86 | void process() { 87 | 88 | result= cdetect->process(image); 89 | } 90 | 91 | 92 | // Returns the image result from the latest processing. 93 | const cv::Mat getLastResult() const { 94 | 95 | return result; 96 | } 97 | 98 | // Deletes all processor objects created by the controller. 99 | ~ColorDetectController() { 100 | 101 | delete cdetect; 102 | } 103 | }; 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /Chapter03/colorDetection.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 3 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | 22 | #include "colordetector.h" 23 | 24 | int main() 25 | { 26 | // 1. Create image processor object 27 | ColorDetector cdetect; 28 | 29 | // 2. Read input image 30 | cv::Mat image= cv::imread("boldt.jpg"); 31 | if (image.empty()) 32 | return 0; 33 | 34 | // 3. Set input parameters 35 | cdetect.setTargetColor(230,190,130); // here blue sky 36 | 37 | // 4. Process the image and display the result 38 | cv::namedWindow("result"); 39 | cv::imshow("result",cdetect.process(image)); 40 | 41 | // or using functor 42 | ColorDetector colordetector(230, 190, 130, // color 43 | 45, true); // Lab threshold 44 | cv::namedWindow("result (functor)"); 45 | cv::imshow("result (functor)",colordetector(image)); 46 | 47 | cv::waitKey(); 48 | 49 | return 0; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /Chapter03/colordetector.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 3 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include "colordetector.h" 20 | #include 21 | 22 | cv::Mat ColorDetector::process(const cv::Mat &image) { 23 | 24 | // re-allocate binary map if necessary 25 | // same size as input image, but 1-channel 26 | result.create(image.size(),CV_8U); 27 | 28 | // Converting to Lab color space 29 | if (useLab) 30 | cv::cvtColor(image, converted, CV_BGR2Lab); 31 | 32 | // get the iterators 33 | cv::Mat_::const_iterator it= image.begin(); 34 | cv::Mat_::const_iterator itend= image.end(); 35 | cv::Mat_::iterator itout= result.begin(); 36 | 37 | // get the iterators of the converted image 38 | if (useLab) { 39 | it = converted.begin(); 40 | itend = converted.end(); 41 | } 42 | 43 | // for each pixel 44 | for ( ; it!= itend; ++it, ++itout) { 45 | 46 | // process each pixel --------------------- 47 | 48 | // compute distance from target color 49 | if (getDistanceToTargetColor(*it) 23 | #include 24 | 25 | class ColorDetector { 26 | 27 | private: 28 | 29 | // minimum acceptable distance 30 | int maxDist; 31 | 32 | // target color 33 | cv::Vec3b target; 34 | 35 | // image containing color converted image 36 | cv::Mat converted; 37 | bool useLab; 38 | 39 | // image containing resulting binary map 40 | cv::Mat result; 41 | 42 | public: 43 | 44 | // empty constructor 45 | // default parameter initialization here 46 | ColorDetector() : maxDist(100), target(0,0,0), useLab(false) {} 47 | 48 | // extra constructor for Lab color space example 49 | ColorDetector(bool useLab) : maxDist(100), target(0,0,0), useLab(useLab) {} 50 | 51 | // full constructor 52 | ColorDetector(uchar blue, uchar green, uchar red, int mxDist=100, bool useLab=false): maxDist(mxDist), useLab(useLab) { 53 | 54 | // target color 55 | setTargetColor(blue, green, red); 56 | } 57 | 58 | // Computes the distance from target color. 59 | int getDistanceToTargetColor(const cv::Vec3b& color) const { 60 | return getColorDistance(color, target); 61 | } 62 | 63 | // Computes the city-block distance between two colors. 64 | int getColorDistance(const cv::Vec3b& color1, const cv::Vec3b& color2) const { 65 | 66 | return abs(color1[0]-color2[0])+ 67 | abs(color1[1]-color2[1])+ 68 | abs(color1[2]-color2[2]); 69 | 70 | // Or: 71 | // return static_cast(cv::norm(cv::Vec3i(color[0]-color2[0],color[1]-color2[1],color[2]-color2[2]))); 72 | 73 | // Or: 74 | // cv::Vec3b dist; 75 | // cv::absdiff(color,color2,dist); 76 | // return cv::sum(dist)[0]; 77 | } 78 | 79 | // Processes the image. Returns a 1-channel binary image. 80 | cv::Mat process(const cv::Mat &image); 81 | 82 | cv::Mat operator()(const cv::Mat &image) { 83 | 84 | cv::Mat input; 85 | input = image; 86 | if (useLab) { // Lab conversion 87 | cv::cvtColor(image, input, CV_BGR2Lab); 88 | } 89 | 90 | cv::Mat output; 91 | // compute absolute difference with target color 92 | cv::absdiff(input,cv::Scalar(target),output); 93 | // split the channels into 3 images 94 | std::vector images; 95 | cv::split(output,images); 96 | // add the 3 channels (saturation might occurs here) 97 | output= images[0]+images[1]+images[2]; 98 | // apply threshold 99 | cv::threshold(output, // input image 100 | output, // output image 101 | maxDist, // threshold (must be < 256) 102 | 255, // max value 103 | cv::THRESH_BINARY_INV); // thresholding type 104 | 105 | return output; 106 | } 107 | 108 | // Getters and setters 109 | 110 | // Sets the color distance threshold. 111 | // Threshold must be positive, otherwise distance threshold 112 | // is set to 0. 113 | void setColorDistanceThreshold(int distance) { 114 | 115 | if (distance<0) 116 | distance=0; 117 | maxDist= distance; 118 | } 119 | 120 | // Gets the color distance threshold 121 | int getColorDistanceThreshold() const { 122 | 123 | return maxDist; 124 | } 125 | 126 | // Sets the color to be detected 127 | void setTargetColor(uchar blue, uchar green, uchar red) { 128 | 129 | // BGR order 130 | target = cv::Vec3b(blue, green, red); 131 | 132 | if (useLab) { 133 | // Temporary 1-pixel image 134 | cv::Mat tmp(1, 1, CV_8UC3); 135 | tmp.at(0, 0) = cv::Vec3b(blue, green, red); 136 | 137 | // Converting the target to Lab color space 138 | cv::cvtColor(tmp, tmp, CV_BGR2Lab); 139 | 140 | target = tmp.at(0, 0); 141 | } 142 | } 143 | 144 | // Sets the color to be detected 145 | void setTargetColor(cv::Vec3b color) { 146 | 147 | target= color; 148 | } 149 | 150 | // Gets the color to be detected 151 | cv::Vec3b getTargetColor() const { 152 | 153 | return target; 154 | } 155 | }; 156 | 157 | 158 | #endif 159 | -------------------------------------------------------------------------------- /Chapter03/controller.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 3 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "colorDetectController.h" 25 | 26 | 27 | int main() 28 | { 29 | // Create the controller 30 | ColorDetectController controller; 31 | 32 | 33 | // To display the result 34 | cv::namedWindow("Image"); 35 | 36 | // The following code simulate a user Interface 37 | // based on the use of a controller 38 | // Interaction with user is simply done 39 | // using key pressed 40 | std::cout << "q: to quit" << std::endl; 41 | std::cout << "f: to input a filename" << std::endl; 42 | std::cout << "t: to input target color values" << std::endl; 43 | std::cout << "c: to input color distance threshold" << std::endl; 44 | std::cout << "v: to view the different parameter values" << std::endl; 45 | std::cout << "r: to run" << std::endl; 46 | 47 | char key=' '; 48 | std::string filename; 49 | 50 | while ((key=getchar()) != 'q') { 51 | 52 | switch (key) { 53 | uchar r,g,b; 54 | case 'f': // read an image 55 | std::cout << std::endl << "Filename? "; 56 | std::cin >> filename; 57 | std::cout << std::endl; 58 | if (controller.setInputImage(filename)) 59 | std::cout << "...image successfully opened" << std::endl; 60 | else 61 | std::cout << "...cannot find image: " << filename << std::endl; 62 | 63 | break; 64 | case 't': // input target color 65 | int ir,ig,ib; 66 | std::cout << std::endl << "Target color? "; 67 | std:: cin >> ir >> ig >> ib; 68 | std::cout << std::endl; 69 | controller.setTargetColor(ir,ig,ib); 70 | break; 71 | case 'c': // input threshold 72 | int th; 73 | std::cout << std::endl << "Color distance threshold? "; 74 | std:: cin >> th; 75 | std::cout << std::endl; 76 | controller.setColorDistanceThreshold(th); 77 | break; 78 | case 'v': // view the parameters 79 | std::cout << std::endl << "Image name: " << filename << std::endl; 80 | controller.getTargetColour(r,g,b); 81 | std::cout << std::endl << "Target color: " 82 | << static_cast(r) << "," 83 | << static_cast(g) << "," 84 | << static_cast(b) << std::endl; 85 | std::cout << std::endl << "Distance thresdhold: " << controller.getColorDistanceThreshold() << std::endl; 86 | std::cout << std::endl; 87 | break; 88 | case 'i': // show input image 89 | cv::imshow("Image",controller.getInputImage()); 90 | cv::waitKey(10); // for window to repaint 91 | break; 92 | case 'r': // run color detection 93 | controller.process(); 94 | cv::imshow("Image",controller.getLastResult()); 95 | cv::waitKey(10); // for window to repaint 96 | break; 97 | } 98 | } 99 | 100 | return 0; 101 | } 102 | 103 | -------------------------------------------------------------------------------- /Chapter03/huesaturation.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 3 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | 26 | void detectHScolor(const cv::Mat& image, // input image 27 | double minHue, double maxHue, // Hue interval 28 | double minSat, double maxSat, // saturation interval 29 | cv::Mat& mask) { // output mask 30 | 31 | // convert into HSV space 32 | cv::Mat hsv; 33 | cv::cvtColor(image, hsv, CV_BGR2HSV); 34 | 35 | // split the 3 channels into 3 images 36 | std::vector channels; 37 | cv::split(hsv, channels); 38 | // channels[0] is the Hue 39 | // channels[1] is the Saturation 40 | // channels[2] is the Value 41 | 42 | // Hue masking 43 | cv::Mat mask1; // under maxHue 44 | cv::threshold(channels[0], mask1, maxHue, 255, cv::THRESH_BINARY_INV); 45 | cv::Mat mask2; // over minHue 46 | cv::threshold(channels[0], mask2, minHue, 255, cv::THRESH_BINARY); 47 | 48 | cv::Mat hueMask; // hue mask 49 | if (minHue < maxHue) 50 | hueMask = mask1 & mask2; 51 | else // if interval crosses the zero-degree axis 52 | hueMask = mask1 | mask2; 53 | 54 | // Saturation masking 55 | // under maxSat 56 | cv::threshold(channels[1], mask1, maxSat, 255, cv::THRESH_BINARY_INV); 57 | // over minSat 58 | cv::threshold(channels[1], mask2, minSat, 255, cv::THRESH_BINARY); 59 | 60 | cv::Mat satMask; // saturation mask 61 | satMask = mask1 & mask2; 62 | 63 | // combined mask 64 | mask = hueMask&satMask; 65 | } 66 | 67 | int main() 68 | { 69 | // read the image 70 | cv::Mat image= cv::imread("boldt.jpg"); 71 | if (!image.data) 72 | return 0; 73 | 74 | // show original image 75 | cv::namedWindow("Original image"); 76 | cv::imshow("Original image",image); 77 | 78 | // convert into HSV space 79 | cv::Mat hsv; 80 | cv::cvtColor(image, hsv, CV_BGR2HSV); 81 | 82 | // split the 3 channels into 3 images 83 | std::vector channels; 84 | cv::split(hsv,channels); 85 | // channels[0] is the Hue 86 | // channels[1] is the Saturation 87 | // channels[2] is the Value 88 | 89 | // display value 90 | cv::namedWindow("Value"); 91 | cv::imshow("Value",channels[2]); 92 | 93 | // display saturation 94 | cv::namedWindow("Saturation"); 95 | cv::imshow("Saturation",channels[1]); 96 | 97 | // display hue 98 | cv::namedWindow("Hue"); 99 | cv::imshow("Hue",channels[0]); 100 | 101 | // image with fixed value 102 | cv::Mat newImage; 103 | cv::Mat tmp(channels[2].clone()); 104 | // Value channel will be 255 for all pixels 105 | channels[2]= 255; 106 | // merge back the channels 107 | cv::merge(channels,hsv); 108 | // re-convert to BGR 109 | cv::cvtColor(hsv,newImage,CV_HSV2BGR); 110 | 111 | cv::namedWindow("Fixed Value Image"); 112 | cv::imshow("Fixed Value Image",newImage); 113 | 114 | // image with fixed saturation 115 | channels[1]= 255; 116 | channels[2]= tmp; 117 | cv::merge(channels,hsv); 118 | cv::cvtColor(hsv,newImage,CV_HSV2BGR); 119 | 120 | cv::namedWindow("Fixed saturation"); 121 | cv::imshow("Fixed saturation",newImage); 122 | 123 | // image with fixed value and fixed saturation 124 | channels[1]= 255; 125 | channels[2]= 255; 126 | cv::merge(channels,hsv); 127 | cv::cvtColor(hsv,newImage,CV_HSV2BGR); 128 | 129 | cv::namedWindow("Fixed saturation/value"); 130 | cv::imshow("Fixed saturation/value",newImage); 131 | 132 | // Testing skin detection 133 | 134 | // read the image 135 | image= cv::imread("girl.jpg"); 136 | if (!image.data) 137 | return 0; 138 | 139 | // show original image 140 | cv::namedWindow("Original image"); 141 | cv::imshow("Original image",image); 142 | 143 | // detect skin tone 144 | cv::Mat mask; 145 | detectHScolor(image, 146 | 160, 10, // hue from 320 degrees to 20 degrees 147 | 25, 166, // saturation from ~0.1 to 0.65 148 | mask); 149 | 150 | // show masked image 151 | cv::Mat detected(image.size(), CV_8UC3, cv::Scalar(0, 0, 0)); 152 | image.copyTo(detected, mask); 153 | cv::imshow("Detection result",detected); 154 | 155 | // A test comparing luminance and brightness 156 | 157 | // create linear intensity image 158 | cv::Mat linear(100,256,CV_8U); 159 | for (int i=0; i<256; i++) { 160 | 161 | linear.col(i)= i; 162 | } 163 | 164 | // create a Lab image 165 | linear.copyTo(channels[0]); 166 | cv::Mat constante(100,256,CV_8U,cv::Scalar(128)); 167 | constante.copyTo(channels[1]); 168 | constante.copyTo(channels[2]); 169 | cv::merge(channels,image); 170 | 171 | // convert back to BGR 172 | cv::Mat brightness; 173 | cv::cvtColor(image,brightness, CV_Lab2BGR); 174 | cv::split(brightness, channels); 175 | 176 | // create combined image 177 | cv::Mat combined(200,256, CV_8U); 178 | cv::Mat half1(combined,cv::Rect(0,0,256,100)); 179 | linear.copyTo(half1); 180 | cv::Mat half2(combined,cv::Rect(0,100,256,100)); 181 | channels[0].copyTo(half2); 182 | 183 | cv::namedWindow("Luminance vs Brightness"); 184 | cv::imshow("Luminance vs Brightness",combined); 185 | 186 | cv::waitKey(); 187 | } 188 | -------------------------------------------------------------------------------- /Chapter04/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # cmake for OpenCV2 Cookbook 2 | # your opencv/build directory should be in your system PATH 3 | 4 | # set minimum required version for cmake 5 | cmake_minimum_required(VERSION 2.8) 6 | 7 | # define the project name 8 | set(project_name "Chapter04") 9 | 10 | # set the project namee 11 | project("${project_name}") 12 | 13 | # add opencv package to the project 14 | find_package( OpenCV REQUIRED ) 15 | MESSAGE("OpenCV version : ${OpenCV_VERSION}") 16 | 17 | # add opencv include directories to the project 18 | include_directories( ${OpenCV_INCLUDE_DIRS} ) 19 | 20 | # add executable 21 | add_executable( histograms histograms.cpp) 22 | add_executable( contentfinder contentfinder.cpp) 23 | add_executable( finder finder.cpp) 24 | add_executable( retrieve retrieve.cpp) 25 | add_executable( integral integral.cpp) 26 | add_executable( tracking tracking.cpp) 27 | 28 | # link libraries 29 | target_link_libraries( histograms ${OpenCV_LIBS}) 30 | target_link_libraries( contentfinder ${OpenCV_LIBS}) 31 | target_link_libraries( finder ${OpenCV_LIBS}) 32 | target_link_libraries( retrieve ${OpenCV_LIBS}) 33 | target_link_libraries( integral ${OpenCV_LIBS}) 34 | target_link_libraries( tracking ${OpenCV_LIBS}) 35 | 36 | -------------------------------------------------------------------------------- /Chapter04/README.txt: -------------------------------------------------------------------------------- 1 | This directory contains material supporting chapter 4 of the cookbook: 2 | Computer Vision Programming using the OpenCV Library. 3 | Second Edition 4 | by Robert Laganiere, Packt Publishing, 2013. 5 | 6 | Files: 7 | histogram.h 8 | histograms.cpp 9 | correspond to Recipes: 10 | Computing the image histogram 11 | Applying Look-up Tables to Modify Image Appearance 12 | 13 | Files: 14 | colorhistogram.h 15 | histogram.h 16 | contentfinder.h 17 | contentfinder.cpp 18 | correspond to Recipe: 19 | Backprojecting a Histogram to Detect Specific Image Content 20 | 21 | Files: 22 | colorhistogram.h 23 | finder.cpp 24 | correspond to Recipe: 25 | Using the Meanshift Algorithm to Find an Object 26 | 27 | Files: 28 | imageComparator.h 29 | retrieve.cpp 30 | correspond to Recipe: 31 | Retrieving Similar Images using Histogram Comparison 32 | 33 | Files: 34 | integral.h 35 | integral.cpp 36 | tracking.cpp 37 | correspond to Recipe: 38 | Counting pixels with integral images 39 | 40 | You need the images: 41 | group.jpg 42 | waves.jpg 43 | waves2.jpg 44 | dog.jpg 45 | baboon1.jpg 46 | baboon3.jpg 47 | beach.jpg 48 | marais.jpg 49 | fundy.jpg 50 | moose.jpg 51 | bear.jpg 52 | polar.jpg 53 | lake.jpg 54 | bike55.bmp 55 | bike65.bmp 56 | -------------------------------------------------------------------------------- /Chapter04/colorhistogram.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 4 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #if !defined COLHISTOGRAM 20 | #define COLHISTOGRAM 21 | 22 | #include 23 | #include 24 | 25 | class ColorHistogram { 26 | 27 | private: 28 | 29 | int histSize[3]; // size of each dimension 30 | float hranges[2]; // range of values 31 | const float* ranges[3]; // array of ranges for each dimension 32 | int channels[3]; // channel to be considered 33 | 34 | public: 35 | 36 | ColorHistogram() { 37 | 38 | // Prepare default arguments for a color histogram 39 | // each dimension has equal size and range 40 | histSize[0]= histSize[1]= histSize[2]= 256; 41 | hranges[0]= 0.0; // BRG range from 0 to 256 42 | hranges[1]= 256.0; 43 | ranges[0]= hranges; // in this class, 44 | ranges[1]= hranges; // all channels have the same range 45 | ranges[2]= hranges; 46 | channels[0]= 0; // the three channels 47 | channels[1]= 1; 48 | channels[2]= 2; 49 | } 50 | 51 | // set histogram size for each dimension 52 | void setSize(int size) { 53 | 54 | // each dimension has equal size 55 | histSize[0]= histSize[1]= histSize[2]= size; 56 | } 57 | 58 | // Computes the histogram. 59 | cv::Mat getHistogram(const cv::Mat &image) { 60 | 61 | cv::Mat hist; 62 | 63 | // BGR color histogram 64 | hranges[0]= 0.0; // BRG range 65 | hranges[1]= 256.0; 66 | channels[0]= 0; // the three channels 67 | channels[1]= 1; 68 | channels[2]= 2; 69 | 70 | // Compute histogram 71 | cv::calcHist(&image, 72 | 1, // histogram of 1 image only 73 | channels, // the channel used 74 | cv::Mat(), // no mask is used 75 | hist, // the resulting histogram 76 | 3, // it is a 3D histogram 77 | histSize, // number of bins 78 | ranges // pixel value range 79 | ); 80 | 81 | return hist; 82 | } 83 | 84 | // Computes the histogram. 85 | cv::SparseMat getSparseHistogram(const cv::Mat &image) { 86 | 87 | cv::SparseMat hist(3, // number of dimensions 88 | histSize, // size of each dimension 89 | CV_32F); 90 | 91 | // BGR color histogram 92 | hranges[0]= 0.0; // BRG range 93 | hranges[1]= 256.0; 94 | channels[0]= 0; // the three channels 95 | channels[1]= 1; 96 | channels[2]= 2; 97 | 98 | // Compute histogram 99 | cv::calcHist(&image, 100 | 1, // histogram of 1 image only 101 | channels, // the channel used 102 | cv::Mat(), // no mask is used 103 | hist, // the resulting histogram 104 | 3, // it is a 3D histogram 105 | histSize, // number of bins 106 | ranges // pixel value range 107 | ); 108 | 109 | return hist; 110 | } 111 | 112 | // Computes the 1D Hue histogram with a mask. 113 | // BGR source image is converted to HSV 114 | // Pixels with low saturation are ignored 115 | cv::Mat getHueHistogram(const cv::Mat &image, 116 | int minSaturation=0) { 117 | 118 | cv::Mat hist; 119 | 120 | // Convert to HSV colour space 121 | cv::Mat hsv; 122 | cv::cvtColor(image, hsv, CV_BGR2HSV); 123 | 124 | // Mask to be used (or not) 125 | cv::Mat mask; 126 | 127 | if (minSaturation>0) { 128 | 129 | // Spliting the 3 channels into 3 images 130 | std::vector v; 131 | cv::split(hsv,v); 132 | 133 | // Mask out the low saturated pixels 134 | cv::threshold(v[1],mask,minSaturation,255, 135 | cv::THRESH_BINARY); 136 | } 137 | 138 | // Prepare arguments for a 1D hue histogram 139 | hranges[0]= 0.0; // range is from 0 to 180 140 | hranges[1]= 180.0; 141 | channels[0]= 0; // the hue channel 142 | 143 | // Compute histogram 144 | cv::calcHist(&hsv, 145 | 1, // histogram of 1 image only 146 | channels, // the channel used 147 | mask, // binary mask 148 | hist, // the resulting histogram 149 | 1, // it is a 1D histogram 150 | histSize, // number of bins 151 | ranges // pixel value range 152 | ); 153 | 154 | return hist; 155 | } 156 | 157 | // Computes the 2D ab histogram. 158 | // BGR source image is converted to Lab 159 | cv::Mat getabHistogram(const cv::Mat &image) { 160 | 161 | cv::Mat hist; 162 | 163 | // Convert to Lab color space 164 | cv::Mat lab; 165 | cv::cvtColor(image, lab, CV_BGR2Lab); 166 | 167 | // Prepare arguments for a 2D color histogram 168 | hranges[0]= 0; 169 | hranges[1]= 256.0; 170 | channels[0]= 1; // the two channels used are ab 171 | channels[1]= 2; 172 | 173 | // Compute histogram 174 | cv::calcHist(&lab, 175 | 1, // histogram of 1 image only 176 | channels, // the channel used 177 | cv::Mat(), // no mask is used 178 | hist, // the resulting histogram 179 | 2, // it is a 2D histogram 180 | histSize, // number of bins 181 | ranges // pixel value range 182 | ); 183 | 184 | return hist; 185 | } 186 | }; 187 | 188 | 189 | #endif 190 | -------------------------------------------------------------------------------- /Chapter04/contentFinder.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 4 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | using namespace std; 21 | 22 | #include 23 | #include 24 | 25 | #include "histogram.h" 26 | #include "contentFinder.h" 27 | #include "colorhistogram.h" 28 | 29 | int main() 30 | { 31 | // Read input image 32 | cv::Mat image= cv::imread("waves2.jpg",0); 33 | if (!image.data) 34 | return 0; 35 | 36 | // define image ROI 37 | cv::Mat imageROI; 38 | imageROI= image(cv::Rect(216,33,24,30)); // Cloud region 39 | 40 | // Display reference patch 41 | cv::namedWindow("Reference"); 42 | cv::imshow("Reference",imageROI); 43 | 44 | // Find histogram of reference 45 | Histogram1D h; 46 | cv::Mat hist= h.getHistogram(imageROI); 47 | cv::namedWindow("Reference Hist"); 48 | cv::imshow("Reference Hist",h.getHistogramImage(imageROI)); 49 | 50 | // Create the content finder 51 | ContentFinder finder; 52 | 53 | // set histogram to be back-projected 54 | finder.setHistogram(hist); 55 | finder.setThreshold(-1.0f); 56 | 57 | // Get back-projection 58 | cv::Mat result1; 59 | result1= finder.find(image); 60 | 61 | // Create negative image and display result 62 | cv::Mat tmp; 63 | result1.convertTo(tmp,CV_8U,-1.0,255.0); 64 | cv::namedWindow("Backprojection result"); 65 | cv::imshow("Backprojection result",tmp); 66 | 67 | // Get binary back-projection 68 | finder.setThreshold(0.12f); 69 | result1= finder.find(image); 70 | 71 | // Draw a rectangle around the reference area 72 | cv::rectangle(image, cv::Rect(216, 33, 24, 30), cv::Scalar(0, 0, 0)); 73 | 74 | // Display image 75 | cv::namedWindow("Image"); 76 | cv::imshow("Image",image); 77 | 78 | // Display result 79 | cv::namedWindow("Detection Result"); 80 | cv::imshow("Detection Result",result1); 81 | 82 | // Load color image 83 | ColorHistogram hc; 84 | cv::Mat color= cv::imread("waves2.jpg"); 85 | 86 | // extract region of interest 87 | imageROI= color(cv::Rect(0,0,100,45)); // blue sky area 88 | 89 | // Get 3D colour histogram (8 bins per channel) 90 | hc.setSize(8); // 8x8x8 91 | cv::Mat shist= hc.getHistogram(imageROI); 92 | 93 | // set histogram to be back-projected 94 | finder.setHistogram(shist); 95 | finder.setThreshold(0.05f); 96 | 97 | // Get back-projection of color histogram 98 | result1= finder.find(color); 99 | 100 | cv::namedWindow("Color Detection Result"); 101 | cv::imshow("Color Detection Result",result1); 102 | 103 | // Second color image 104 | cv::Mat color2= cv::imread("dog.jpg"); 105 | 106 | cv::namedWindow("Second Image"); 107 | cv::imshow("Second Image",color2); 108 | 109 | // Get back-projection of color histogram 110 | cv::Mat result2= finder.find(color2); 111 | 112 | cv::namedWindow("Result color (2)"); 113 | cv::imshow("Result color (2)",result2); 114 | 115 | // Get ab color histogram 116 | hc.setSize(256); // 256x256 117 | cv::Mat colorhist= hc.getabHistogram(imageROI); 118 | 119 | // display 2D histogram 120 | colorhist.convertTo(tmp,CV_8U,-1.0,255.0); 121 | cv::namedWindow("ab histogram"); 122 | cv::imshow("ab histogram",tmp); 123 | 124 | // set histogram to be back-projected 125 | finder.setHistogram(colorhist); 126 | finder.setThreshold(0.05f); 127 | 128 | // Convert to Lab space 129 | cv::Mat lab; 130 | cv::cvtColor(color, lab, CV_BGR2Lab); 131 | 132 | // Get back-projection of ab histogram 133 | int ch[2]={1,2}; 134 | result1= finder.find(lab,0,256.0f,ch); 135 | 136 | cv::namedWindow("Result ab (1)"); 137 | cv::imshow("Result ab (1)",result1); 138 | 139 | // Second colour image 140 | cv::cvtColor(color2, lab, CV_BGR2Lab); 141 | 142 | // Get back-projection of ab histogram 143 | result2= finder.find(lab,0,256.0,ch); 144 | 145 | cv::namedWindow("Result ab (2)"); 146 | cv::imshow("Result ab (2)",result2); 147 | 148 | // Draw a rectangle around the reference sky area 149 | cv::rectangle(color,cv::Rect(0,0,100,45),cv::Scalar(0,0,0)); 150 | cv::namedWindow("Color Image"); 151 | cv::imshow("Color Image",color); 152 | 153 | 154 | // Get Hue colour histogram 155 | hc.setSize(180); // 180 bins 156 | colorhist= hc.getHueHistogram(imageROI); 157 | 158 | // set histogram to be back-projected 159 | finder.setHistogram(colorhist); 160 | 161 | // Convert to HSV space 162 | cv::Mat hsv; 163 | cv::cvtColor(color, hsv, CV_BGR2HSV); 164 | 165 | // Get back-projection of hue histogram 166 | ch[0]=0; 167 | result1= finder.find(hsv,0.0f,180.0f,ch); 168 | 169 | cv::namedWindow("Result Hue (1)"); 170 | cv::imshow("Result Hue (1)",result1); 171 | 172 | // Second colour image 173 | color2= cv::imread("dog.jpg"); 174 | 175 | // Convert to HSV space 176 | cv::cvtColor(color2, hsv, CV_BGR2HSV); 177 | 178 | // Get back-projection of hue histogram 179 | result2= finder.find(hsv,0.0f,180.0f,ch); 180 | 181 | cv::namedWindow("Result Hue (2)"); 182 | cv::imshow("Result Hue (2)",result2); 183 | 184 | cv::waitKey(); 185 | return 0; 186 | } 187 | 188 | -------------------------------------------------------------------------------- /Chapter04/contentFinder.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 4 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #if !defined OFINDER 20 | #define OFINDER 21 | 22 | #include 23 | #include 24 | 25 | class ContentFinder { 26 | 27 | private: 28 | 29 | // histogram parameters 30 | float hranges[2]; 31 | const float* ranges[3]; 32 | int channels[3]; 33 | 34 | float threshold; // decision threshold 35 | cv::Mat histogram; // histogram can be sparse 36 | cv::SparseMat shistogram; // or not 37 | bool isSparse; 38 | 39 | public: 40 | 41 | ContentFinder() : threshold(0.1f), isSparse(false) { 42 | 43 | // in this class, 44 | // all channels have the same range 45 | ranges[0]= hranges; 46 | ranges[1]= hranges; 47 | ranges[2]= hranges; 48 | } 49 | 50 | // Sets the threshold on histogram values [0,1] 51 | void setThreshold(float t) { 52 | 53 | threshold= t; 54 | } 55 | 56 | // Gets the threshold 57 | float getThreshold() { 58 | 59 | return threshold; 60 | } 61 | 62 | // Sets the reference histogram 63 | void setHistogram(const cv::Mat& h) { 64 | 65 | isSparse= false; 66 | cv::normalize(h,histogram,1.0); 67 | } 68 | 69 | // Sets the reference histogram 70 | void setHistogram(const cv::SparseMat& h) { 71 | 72 | isSparse= true; 73 | cv::normalize(h,shistogram,1.0,cv::NORM_L2); 74 | } 75 | 76 | // All channels used, with range [0,256[ 77 | cv::Mat find(const cv::Mat& image) { 78 | 79 | cv::Mat result; 80 | 81 | hranges[0]= 0.0; // default range [0,256[ 82 | hranges[1]= 256.0; 83 | channels[0]= 0; // the three channels 84 | channels[1]= 1; 85 | channels[2]= 2; 86 | 87 | return find(image, hranges[0], hranges[1], channels); 88 | } 89 | 90 | // Finds the pixels belonging to the histogram 91 | cv::Mat find(const cv::Mat& image, float minValue, float maxValue, int *channels) { 92 | 93 | cv::Mat result; 94 | 95 | hranges[0]= minValue; 96 | hranges[1]= maxValue; 97 | 98 | if (isSparse) { // call the right function based on histogram type 99 | 100 | for (int i=0; ichannels[i]= channels[i]; 102 | 103 | cv::calcBackProject(&image, 104 | 1, // we only use one image at a time 105 | channels, // vector specifying what histogram dimensions belong to what image channels 106 | shistogram, // the histogram we are using 107 | result, // the resulting back projection image 108 | ranges, // the range of values, for each dimension 109 | 255.0 // the scaling factor is chosen such that a histogram value of 1 maps to 255 110 | ); 111 | 112 | } else { 113 | 114 | for (int i=0; ichannels[i]= channels[i]; 116 | 117 | cv::calcBackProject(&image, 118 | 1, // we only use one image at a time 119 | channels, // vector specifying what histogram dimensions belong to what image channels 120 | histogram, // the histogram we are using 121 | result, // the resulting back projection image 122 | ranges, // the range of values, for each dimension 123 | 255.0 // the scaling factor is chosen such that a histogram value of 1 maps to 255 124 | ); 125 | } 126 | 127 | // Threshold back projection to obtain a binary image 128 | if (threshold>0.0) 129 | cv::threshold(result, result, 255.0*threshold, 255.0, cv::THRESH_BINARY); 130 | 131 | return result; 132 | } 133 | 134 | }; 135 | 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /Chapter04/finder.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 4 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | using namespace std; 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "contentFinder.h" 28 | #include "colorhistogram.h" 29 | 30 | int main() 31 | { 32 | // Read reference image 33 | cv::Mat image= cv::imread("baboon1.jpg"); 34 | if (!image.data) 35 | return 0; 36 | 37 | // Define ROI 38 | cv::Mat imageROI= image(cv::Rect(110,260,35,40)); 39 | cv::rectangle(image, cv::Rect(110,260,35,40),cv::Scalar(0,0,255)); 40 | 41 | // Display image (just half of it) 42 | cv::Mat window(image, cv::Rect(0, 2*image.rows/5, image.cols, image.rows/2)); 43 | cv::namedWindow("Image"); 44 | cv::imshow("Image",window); 45 | 46 | // Get the Hue histogram 47 | int minSat=65; 48 | ColorHistogram hc; 49 | cv::Mat colorhist= hc.getHueHistogram(imageROI,minSat); 50 | 51 | ContentFinder finder; 52 | finder.setHistogram(colorhist); 53 | finder.setThreshold(0.2f); 54 | 55 | // Convert to HSV space (just for display) 56 | cv::Mat hsv; 57 | cv::cvtColor(image, hsv, CV_BGR2HSV); 58 | 59 | // Split the image 60 | vector v; 61 | cv::split(hsv,v); 62 | 63 | // Eliminate pixels with low saturation 64 | cv::threshold(v[1],v[1],minSat,255,cv::THRESH_BINARY); 65 | cv::namedWindow("Saturation mask"); 66 | cv::imshow("Saturation mask",v[1]); 67 | 68 | //-------------- 69 | // Second image 70 | image= cv::imread("baboon3.jpg"); 71 | 72 | // Display image (just half of it) 73 | cv::Mat window2(image, cv::Rect(0, 2 * image.rows / 5, image.cols, image.rows / 2)); 74 | cv::namedWindow("Image 2"); 75 | cv::imshow("Image 2",window2); 76 | 77 | // Convert to HSV space 78 | cv::cvtColor(image, hsv, CV_BGR2HSV); 79 | 80 | // Get back-projection of hue histogram 81 | int ch[1]={0}; 82 | finder.setThreshold(-1.0f); // no thresholding 83 | cv::Mat result= finder.find(hsv,0.0f,180.0f,ch); 84 | 85 | // Display back projection result 86 | cv::namedWindow("Backprojection on second image"); 87 | cv::imshow("Backprojection on second image",result); 88 | 89 | // initial window position 90 | cv::Rect rect(110,260,35,40); 91 | cv::rectangle(image, rect, cv::Scalar(0,0,255)); 92 | 93 | // search objet with mean shift 94 | cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER,10,0.01); 95 | cout << "meanshift= " << cv::meanShift(result,rect,criteria) << endl; 96 | 97 | // draw output window 98 | cv::rectangle(image, rect, cv::Scalar(0,255,0)); 99 | 100 | // Display image 101 | cv::Mat window2r(image, cv::Rect(0, 2 * image.rows / 5, image.cols, image.rows / 2)); 102 | cv::namedWindow("Image 2 result"); 103 | cv::imshow("Image 2 result",window2r); 104 | 105 | cv::waitKey(); 106 | return 0; 107 | } -------------------------------------------------------------------------------- /Chapter04/histograms.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 4 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | #include 19 | using namespace std; 20 | 21 | #include 22 | #include 23 | #include 24 | #include "histogram.h" 25 | 26 | int main() 27 | { 28 | // Read input image 29 | cv::Mat image= cv::imread("group.jpg",0); 30 | if (!image.data) 31 | return 0; 32 | // Resize by 70% for book printing 33 | cv::resize(image, image, cv::Size(), 0.7, 0.7); 34 | 35 | // save grayscale image 36 | cv::imwrite("groupBW.jpg", image); 37 | 38 | // Display the image 39 | cv::namedWindow("Image"); 40 | cv::imshow("Image",image); 41 | 42 | // The histogram object 43 | Histogram1D h; 44 | 45 | // Compute the histogram 46 | cv::Mat histo= h.getHistogram(image); 47 | 48 | // Loop over each bin 49 | for (int i=0; i<256; i++) 50 | cout << "Value " << i << " = " << histo.at(i) << endl; 51 | 52 | // Display a histogram as an image 53 | cv::namedWindow("Histogram"); 54 | cv::imshow("Histogram",h.getHistogramImage(image)); 55 | 56 | // creating a binary image by thresholding at the valley 57 | cv::Mat thresholded; // output binary image 58 | cv::threshold(image,thresholded, 59 | 60, // threshold value 60 | 255, // value assigned to pixels over threshold value 61 | cv::THRESH_BINARY); // thresholding type 62 | 63 | // Display the thresholded image 64 | cv::namedWindow("Binary Image"); 65 | cv::imshow("Binary Image",thresholded); 66 | thresholded = 255 - thresholded; 67 | cv::imwrite("binary.bmp",thresholded); 68 | 69 | // Equalize the image 70 | cv::Mat eq= h.equalize(image); 71 | 72 | // Show the result 73 | cv::namedWindow("Equalized Image"); 74 | cv::imshow("Equalized Image",eq); 75 | 76 | // Show the new histogram 77 | cv::namedWindow("Equalized Histogram"); 78 | cv::imshow("Equalized Histogram",h.getHistogramImage(eq)); 79 | 80 | // Stretch the image, setting the 1% of pixels at black and 1% at white 81 | cv::Mat str= h.stretch(image,0.01f); 82 | 83 | // Show the result 84 | cv::namedWindow("Stretched Image"); 85 | cv::imshow("Stretched Image",str); 86 | 87 | // Show the new histogram 88 | cv::namedWindow("Stretched Histogram"); 89 | cv::imshow("Stretched Histogram",h.getHistogramImage(str)); 90 | 91 | // Create an image inversion table 92 | int dim(256); 93 | cv::Mat lut(1, // 1 dimension 94 | &dim, // 256 entries 95 | CV_8U); // uchar 96 | // or cv::Mat lut(256,1,CV_8U); 97 | 98 | for (int i=0; i<256; i++) { 99 | 100 | lut.at(i)= 255-i; 101 | } 102 | 103 | // Apply lookup and display negative image 104 | cv::namedWindow("Negative image"); 105 | cv::imshow("Negative image",h.applyLookUp(image,lut)); 106 | 107 | cv::waitKey(); 108 | return 0; 109 | } 110 | 111 | -------------------------------------------------------------------------------- /Chapter04/imageComparator.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 4 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | #if !defined ICOMPARATOR 19 | #define ICOMPARATOR 20 | 21 | #include 22 | #include 23 | #include "colorhistogram.h" 24 | 25 | class ImageComparator { 26 | 27 | private: 28 | 29 | cv::Mat refH; // reference histogram 30 | cv::Mat inputH; // histogram of input image 31 | 32 | ColorHistogram hist; 33 | int nBins; // number of bins used in each color channel 34 | 35 | public: 36 | 37 | ImageComparator() :nBins(8) { 38 | 39 | } 40 | 41 | // Set number of bins used when comparing the histograms 42 | void setNumberOfBins( int bins) { 43 | 44 | nBins= bins; 45 | } 46 | 47 | int getNumberOfBins() { 48 | 49 | return nBins; 50 | } 51 | 52 | // compute histogram of reference image 53 | void setReferenceImage(const cv::Mat& image) { 54 | 55 | hist.setSize(nBins); 56 | refH= hist.getHistogram(image); 57 | } 58 | 59 | // compare the image using their BGR histograms 60 | double compare(const cv::Mat& image) { 61 | 62 | inputH= hist.getHistogram(image); 63 | 64 | return cv::compareHist(refH,inputH,CV_COMP_INTERSECT); 65 | } 66 | }; 67 | 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /Chapter04/integral.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 4 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "integral.h" 25 | 26 | int main() 27 | { 28 | cv::Mat image= cv::imread("book.jpg",0); 29 | if (!image.data) 30 | return 0; 31 | // rotate the image for easier display 32 | cv::transpose(image, image); 33 | cv::flip(image, image, 0); 34 | 35 | // display original image 36 | cv::namedWindow("Original Image"); 37 | cv::imshow("Original Image",image); 38 | 39 | // using a fixed threshold 40 | cv::Mat binaryFixed; 41 | cv::Mat binaryAdaptive; 42 | cv::threshold(image,binaryFixed,70,255,cv::THRESH_BINARY); 43 | 44 | // using as adaptive threshold 45 | int blockSize= 21; // size of the neighborhood 46 | int threshold=10; // pixel will be compared to (mean-threshold) 47 | 48 | int64 time; 49 | time= cv::getTickCount(); 50 | cv::adaptiveThreshold(image, // input image 51 | binaryAdaptive, // output binary image 52 | 255, // max value for output 53 | cv::ADAPTIVE_THRESH_MEAN_C, // adaptive method 54 | cv::THRESH_BINARY, // threshold type 55 | blockSize, // size of the block 56 | threshold); // threshold used 57 | time= cv::getTickCount()-time; 58 | std::cout << "time (adaptiveThreshold)= " << time << std::endl; 59 | 60 | // compute integral image 61 | IntegralImage integral(image); 62 | 63 | // test integral result 64 | std::cout << "sum=" << integral(18,45,30,50) << std::endl; 65 | cv::Mat test(image,cv::Rect(18,45,30,50)); 66 | cv::Scalar t= cv::sum(test); 67 | std::cout << "sum test=" << t[0] << std::endl; 68 | 69 | cv::namedWindow("Fixed Threshold"); 70 | cv::imshow("Fixed Threshold",binaryFixed); 71 | 72 | cv::namedWindow("Adaptive Threshold"); 73 | cv::imshow("Adaptive Threshold",binaryAdaptive); 74 | 75 | cv::Mat binary= image.clone(); 76 | 77 | time= cv::getTickCount(); 78 | int nl= binary.rows; // number of lines 79 | int nc= binary.cols; // total number of elements per line 80 | 81 | // compute integral image 82 | cv::Mat iimage; 83 | cv::integral(image,iimage,CV_32S); 84 | 85 | // for each row 86 | int halfSize= blockSize/2; 87 | for (int j=halfSize; j(j); 91 | int* idata1= iimage.ptr(j-halfSize); 92 | int* idata2= iimage.ptr(j+halfSize+1); 93 | 94 | // for pixel of a line 95 | for (int i=halfSize; i= filtered; 122 | time= cv::getTickCount()-time; 123 | 124 | std::cout << "time filtered= " << time << std::endl; 125 | 126 | cv::namedWindow("Adaptive Threshold (filtered)"); 127 | cv::imshow("Adaptive Threshold (filtered)",binaryFiltered); 128 | 129 | cv::waitKey(); 130 | } 131 | -------------------------------------------------------------------------------- /Chapter04/integral.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 4 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #if !defined IINTEGRAL 20 | #define IINTEGRAL 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | template 29 | class IntegralImage { 30 | 31 | cv::Mat integralImage; 32 | 33 | public: 34 | 35 | IntegralImage(cv::Mat image) { 36 | 37 | // (costly) computation of the integral image 38 | cv::integral(image,integralImage,cv::DataType::type); 39 | } 40 | 41 | // compute sum over sub-regions of any size from 4 pixel access 42 | cv::Vec operator()(int xo, int yo, int width, int height) { 43 | 44 | // window at (xo,yo) of size width by height 45 | return (integralImage.at >(yo+height,xo+width) 46 | -integralImage.at >(yo+height,xo) 47 | -integralImage.at >(yo,xo+width) 48 | +integralImage.at >(yo,xo)); 49 | } 50 | 51 | // compute sum over sub-regions of any size from 4 pixel access 52 | cv::Vec operator()(int x, int y, int radius) { 53 | 54 | // square window centered at (x,y) of size 2*radius+1 55 | return (integralImage.at >(y+radius+1,x+radius+1) 56 | -integralImage.at >(y+radius+1,x-radius) 57 | -integralImage.at >(y-radius,x+radius+1) 58 | +integralImage.at >(y-radius,x-radius)); 59 | } 60 | }; 61 | 62 | // convert to a multi-channel image made of binary planes 63 | // nPlanes must be a power of 2 64 | void convertToBinaryPlanes(const cv::Mat& input, cv::Mat& output, int nPlanes) { 65 | 66 | // number of bits to mask out 67 | int n= 8-static_cast(log(static_cast(nPlanes))/log(2.0)); 68 | // mask used to eliminate least significant bits 69 | uchar mask= 0xFF< planes; 73 | // reduce to nBins bins by eliminating least significant bits 74 | cv::Mat reduced= input&mask; 75 | 76 | // compute each binary image plane 77 | for (int i=0; i 19 | using namespace std; 20 | 21 | #include 22 | #include 23 | 24 | #include "imageComparator.h" 25 | 26 | int main() 27 | { 28 | // Read reference image 29 | cv::Mat image= cv::imread("waves.jpg"); 30 | if (!image.data) 31 | return 0; 32 | 33 | // Display image 34 | cv::namedWindow("Query Image"); 35 | cv::imshow("Query Image",image); 36 | 37 | ImageComparator c; 38 | c.setReferenceImage(image); 39 | 40 | // Read an image and compare it with reference 41 | cv::Mat input= cv::imread("dog.jpg"); 42 | cout << "waves vs dog: " << c.compare(input) << endl; 43 | 44 | // Read an image and compare it with reference 45 | input= cv::imread("marais.jpg"); 46 | cout << "waves vs marais: " << c.compare(input) << endl; 47 | 48 | // Read an image and compare it with reference 49 | input= cv::imread("bear.jpg"); 50 | cout << "waves vs bear: " << c.compare(input) << endl; 51 | 52 | // Read an image and compare it with reference 53 | input= cv::imread("beach.jpg"); 54 | cout << "waves vs beach: " << c.compare(input) << endl; 55 | 56 | // Read an image and compare it with reference 57 | input= cv::imread("polar.jpg"); 58 | cout << "waves vs polar: " << c.compare(input) << endl; 59 | 60 | // Read an image and compare it with reference 61 | input= cv::imread("moose.jpg"); 62 | cout << "waves vs moose: " << c.compare(input) << endl; 63 | 64 | // Read an image and compare it with reference 65 | input= cv::imread("lake.jpg"); 66 | cout << "waves vs lake: " << c.compare(input) << endl; 67 | 68 | // Read an image and compare it with reference 69 | input= cv::imread("fundy.jpg"); 70 | cout << "waves vs fundy: " << c.compare(input) << endl; 71 | 72 | cv::waitKey(); 73 | return 0; 74 | } -------------------------------------------------------------------------------- /Chapter04/tracking.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 4 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | #include "histogram.h" 27 | #include "integral.h" 28 | 29 | int main() 30 | { 31 | // Open image 32 | cv::Mat image= cv::imread("bike55.bmp",0); 33 | // define image roi 34 | int xo=97, yo=112; 35 | int width=25, height=30; 36 | cv::Mat roi(image,cv::Rect(xo,yo,width,height)); 37 | 38 | // compute sum 39 | // returns a Scalar to work with multi-channel images 40 | cv::Scalar sum= cv::sum(roi); 41 | std::cout << sum[0] << std::endl; 42 | 43 | // compute integral image 44 | cv::Mat integralImage; 45 | cv::integral(image,integralImage,CV_32S); 46 | // get sum over an area using three additions/subtractions 47 | int sumInt= integralImage.at(yo+height,xo+width) 48 | -integralImage.at(yo+height,xo) 49 | -integralImage.at(yo,xo+width) 50 | +integralImage.at(yo,xo); 51 | std::cout << sumInt << std::endl; 52 | 53 | // histogram of 16 bins 54 | Histogram1D h; 55 | h.setNBins(16); 56 | // compute histogram over image roi 57 | cv::Mat refHistogram= h.getHistogram(roi); 58 | 59 | cv::namedWindow("Reference Histogram"); 60 | cv::imshow("Reference Histogram",h.getHistogramImage(roi,16)); 61 | std::cout << refHistogram << std::endl; 62 | 63 | // first create 16-plane binary image 64 | cv::Mat planes; 65 | convertToBinaryPlanes(image,planes,16); 66 | // then compute integral image 67 | IntegralImage intHisto(planes); 68 | 69 | 70 | // for testing compute a histogram of 16 bins with integral image 71 | cv::Vec histogram= intHisto(xo,yo,width,height); 72 | std::cout<< histogram << std::endl; 73 | 74 | cv::namedWindow("Reference Histogram (2)"); 75 | cv::Mat im= h.getImageOfHistogram(cv::Mat(histogram),16); 76 | cv::imshow("Reference Histogram (2)",im); 77 | 78 | // search in second image 79 | cv::Mat secondImage= cv::imread("bike65.bmp",0); 80 | if (!secondImage.data) 81 | return 0; 82 | 83 | // first create 16-plane binary image 84 | convertToBinaryPlanes(secondImage,planes,16); 85 | // then compute integral image 86 | IntegralImage intHistogram(planes); 87 | 88 | // compute histogram of 16 bins with integral image (testing) 89 | histogram= intHistogram(135,114,width,height); 90 | std::cout<< histogram << std::endl; 91 | 92 | cv::namedWindow("Current Histogram"); 93 | cv::Mat im2= h.getImageOfHistogram(cv::Mat(histogram),16); 94 | cv::imshow("Current Histogram",im2); 95 | 96 | std::cout << "Distance= " << cv::compareHist(refHistogram,histogram,CV_COMP_INTERSECT) << std::endl; 97 | 98 | double maxSimilarity=0.0; 99 | int xbest, ybest; 100 | // loop over a horizontal strip around girl location in initial image 101 | for (int y=110; y<120; y++) { 102 | for (int x=0; xmaxSimilarity) { 111 | 112 | xbest= x; 113 | ybest= y; 114 | maxSimilarity= distance; 115 | } 116 | 117 | std::cout << "Distance(" << x << "," << y << ")=" << distance << std::endl; 118 | } 119 | } 120 | 121 | std::cout << "Best solution= (" << xbest << "," << ybest << ")=" << maxSimilarity << std::endl; 122 | 123 | // draw a rectangle around target object 124 | cv::rectangle(image,cv::Rect(xo,yo,width,height),0); 125 | cv::namedWindow("Initial Image"); 126 | cv::imshow("Initial Image",image); 127 | 128 | cv::namedWindow("New Image"); 129 | cv::imshow("New Image",secondImage); 130 | 131 | // draw rectangle at best location 132 | cv::rectangle(secondImage,cv::Rect(xbest,ybest,width,height),0); 133 | // draw rectangle around search area 134 | cv::rectangle(secondImage,cv::Rect(0,110,secondImage.cols,height+10),255); 135 | cv::namedWindow("Object location"); 136 | cv::imshow("Object location",secondImage); 137 | 138 | cv::waitKey(); 139 | 140 | } -------------------------------------------------------------------------------- /Chapter05/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # cmake for OpenCV2 Cookbook 2 | # your opencv/build directory should be in your system PATH 3 | 4 | # set minimum required version for cmake 5 | cmake_minimum_required(VERSION 2.8) 6 | 7 | # define the project name 8 | set(project_name "Chapter05") 9 | 10 | # set the project namee 11 | project("${project_name}") 12 | 13 | # add opencv package to the project 14 | find_package( OpenCV REQUIRED ) 15 | MESSAGE("OpenCV version : ${OpenCV_VERSION}") 16 | 17 | # add opencv include directories to the project 18 | include_directories( ${OpenCV_INCLUDE_DIRS} ) 19 | 20 | # add executable 21 | add_executable( morphology morphology.cpp) 22 | add_executable( morpho2 morpho2.cpp) 23 | add_executable( mserFeatures mserFeatures.cpp) 24 | add_executable( segment segment.cpp) 25 | 26 | # link libraries 27 | target_link_libraries( morphology ${OpenCV_LIBS}) 28 | target_link_libraries( morpho2 ${OpenCV_LIBS}) 29 | target_link_libraries( mserFeatures ${OpenCV_LIBS}) 30 | target_link_libraries( segment ${OpenCV_LIBS}) 31 | 32 | -------------------------------------------------------------------------------- /Chapter05/README.txt: -------------------------------------------------------------------------------- 1 | This directory contains material supporting chapter 5 of the cookbook: 2 | Computer Vision Programming using the OpenCV Library. 3 | Second Edition 4 | by Robert Laganiere, Packt Publishing, 2013. 5 | 6 | File: 7 | morphology.cpp 8 | correspond to Recipes: 9 | Eroding and Dilating Images using Morphological Filters 10 | Opening and Closing Images using Morphological Filters 11 | 12 | Files: 13 | morpho2.cpp 14 | morphoFeatures.h 15 | correspond to Recipe: 16 | Detecting edges and corners using morphological filters 17 | 18 | Files: 19 | mserFeature.cpp 20 | mserFeatures.h 21 | correspond to Recipe: 22 | Extracting distinctive regions using MSER 23 | 24 | Files: 25 | segment.cpp 26 | watershedSegmentation.h 27 | correspond to Recipes: 28 | Segmenting images using watersheds 29 | Extracting foreground objects with the GrabCut algorithm 30 | 31 | You need the images: 32 | building.jpg 33 | binary.bmp 34 | group.jpg 35 | tower.jpg 36 | square.bmp 37 | -------------------------------------------------------------------------------- /Chapter05/morpho2.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 5 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include "morphoFeatures.h" 23 | 24 | int main() 25 | { 26 | // Read input image 27 | cv::Mat image= cv::imread("building.jpg",0); 28 | if (!image.data) 29 | return 0; 30 | // resize for book printing 31 | cv::resize(image, image, cv::Size(), 0.7, 0.7); 32 | 33 | // Display the image 34 | cv::namedWindow("Image"); 35 | cv::imshow("Image",image); 36 | 37 | // Create the morphological features instance 38 | MorphoFeatures morpho; 39 | morpho.setThreshold(40); 40 | 41 | // Get the edges 42 | cv::Mat edges; 43 | edges= morpho.getEdges(image); 44 | 45 | // Display the edge image 46 | cv::namedWindow("Edge Image"); 47 | cv::imshow("Edge Image",edges); 48 | 49 | // Get the corners 50 | morpho.setThreshold(-1); 51 | cv::Mat corners; 52 | corners= morpho.getCorners(image); 53 | cv::morphologyEx(corners,corners,cv::MORPH_TOPHAT,cv::Mat()); 54 | cv::threshold(corners, corners, 35, 255, cv::THRESH_BINARY_INV); 55 | 56 | // Display the corner image 57 | cv::namedWindow("Corner Image"); 58 | cv::imshow("Corner Image",corners); 59 | 60 | // Display the corner on the image 61 | morpho.drawOnImage(corners,image); 62 | cv::namedWindow("Corners on Image"); 63 | cv::imshow("Corners on Image",image); 64 | 65 | // Read and display image of square 66 | image= cv::imread("square.bmp",0); 67 | cv::namedWindow("Square Image"); 68 | cv::imshow("Square Image",image); 69 | 70 | // Creating the cross-shaped structuring element 71 | cv::Mat cross(5,5,CV_8U,cv::Scalar(0)); 72 | for (int i=0; i<5; i++) { 73 | 74 | cross.at(2,i)= 1; 75 | cross.at(i,2)= 1; 76 | } 77 | 78 | // Dilate with a cross 79 | cv::Mat result; 80 | cv::dilate(image,result,cross); 81 | 82 | // Display the result 83 | cv::namedWindow("Dilated square with cross"); 84 | cv::imshow("Dilated square with cross",result); 85 | 86 | // Creating the diamond-shaped structuring element 87 | cv::Mat diamond(5,5,CV_8U,cv::Scalar(1)); 88 | diamond.at(0,0)= 0; 89 | diamond.at(0,1)= 0; 90 | diamond.at(1,0)= 0; 91 | diamond.at(4,4)= 0; 92 | diamond.at(3,4)= 0; 93 | diamond.at(4,3)= 0; 94 | diamond.at(4,0)= 0; 95 | diamond.at(4,1)= 0; 96 | diamond.at(3,0)= 0; 97 | diamond.at(0,4)= 0; 98 | diamond.at(0,3)= 0; 99 | diamond.at(1,4)= 0; 100 | 101 | // Erode with a diamond 102 | cv::Mat result2; 103 | cv::erode(result,result2,diamond); 104 | 105 | // Display the result 106 | cv::namedWindow("Eroded square with diamond"); 107 | cv::imshow("Eroded square with diamond",result2); 108 | 109 | // Combine the images into one 110 | cv::Mat final(100,300,CV_8U); 111 | cv::Mat window= final(cv::Rect(0,0,100,100)); 112 | image.copyTo(window); 113 | window= final(cv::Rect(100,0,100,100)); 114 | result.copyTo(window); 115 | window= final(cv::Rect(200,0,100,100)); 116 | result2.copyTo(window); 117 | 118 | // Display the combined result 119 | cv::namedWindow("Combined"); 120 | cv::imshow("Combined",final); 121 | 122 | // Save combined result 123 | cv::imwrite("squares.bmp",final); 124 | 125 | cv::waitKey(); 126 | 127 | return 0; 128 | } 129 | -------------------------------------------------------------------------------- /Chapter05/morphoFeatures.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 5 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #if !defined MORPHOF 20 | #define MORPHOF 21 | 22 | #include 23 | #include 24 | 25 | class MorphoFeatures { 26 | 27 | private: 28 | 29 | // threshold to produce binary image 30 | int threshold; 31 | // structuring elements used in corner detection 32 | cv::Mat_ cross; 33 | cv::Mat_ diamond; 34 | cv::Mat_ square; 35 | cv::Mat_ x; 36 | 37 | void applyThreshold(cv::Mat& result) { 38 | 39 | // Apply threshold on result 40 | if (threshold>0) 41 | cv::threshold(result, result, threshold, 255, cv::THRESH_BINARY_INV); 42 | } 43 | 44 | public: 45 | 46 | MorphoFeatures() : threshold(-1), 47 | cross(5, 5), diamond(5, 5), square(5, 5), x(5, 5) { 48 | 49 | // Creating the cross-shaped structuring element 50 | cross << 51 | 0, 0, 1, 0, 0, 52 | 0, 0, 1, 0, 0, 53 | 1, 1, 1, 1, 1, 54 | 0, 0, 1, 0, 0, 55 | 0, 0, 1, 0, 0; 56 | 57 | // Creating the diamond-shaped structuring element 58 | diamond << 59 | 0, 0, 1, 0, 0, 60 | 0, 1, 1, 1, 0, 61 | 1, 1, 1, 1, 1, 62 | 0, 1, 1, 1, 0, 63 | 0, 0, 1, 0, 0; 64 | 65 | // Creating the x-shaped structuring element 66 | x << 67 | 1, 0, 0, 0, 1, 68 | 0, 1, 0, 1, 0, 69 | 0, 0, 1, 0, 0, 70 | 0, 1, 0, 1, 0, 71 | 1, 0, 0, 0, 1; 72 | 73 | // Creating the square-shaped structuring element 74 | x << 75 | 1, 1, 1, 1, 1, 76 | 1, 1, 1, 1, 1, 77 | 1, 1, 1, 1, 1, 78 | 1, 1, 1, 1, 1, 79 | 1, 1, 1, 1, 1; 80 | } 81 | 82 | void setThreshold(int t) { 83 | 84 | threshold= t; 85 | } 86 | 87 | int getThreshold() const { 88 | 89 | return threshold; 90 | } 91 | 92 | cv::Mat getEdges(const cv::Mat &image) { 93 | 94 | // Get the gradient image 95 | cv::Mat result; 96 | cv::morphologyEx(image,result,cv::MORPH_GRADIENT,cv::Mat()); 97 | 98 | // Apply threshold to obtain a binary image 99 | applyThreshold(result); 100 | 101 | return result; 102 | } 103 | 104 | cv::Mat getCorners(const cv::Mat &image) { 105 | 106 | cv::Mat result; 107 | 108 | // Dilate with a cross 109 | cv::dilate(image,result,cross); 110 | 111 | // Erode with a diamond 112 | cv::erode(result,result,diamond); 113 | 114 | cv::Mat result2; 115 | // Dilate with a X 116 | cv::dilate(image,result2,x); 117 | 118 | // Erode with a square 119 | cv::erode(result2,result2,square); 120 | 121 | // Corners are obtained by differencing 122 | // the two closed images 123 | cv::absdiff(result2,result,result); 124 | 125 | // Apply threshold to obtain a binary image 126 | applyThreshold(result); 127 | 128 | return result; 129 | } 130 | 131 | void drawOnImage(const cv::Mat& binary, cv::Mat& image) { 132 | 133 | cv::Mat_::const_iterator it= binary.begin(); 134 | cv::Mat_::const_iterator itend= binary.end(); 135 | 136 | // for each pixel 137 | for (int i=0; it!= itend; ++it,++i) { 138 | if (!*it) 139 | cv::circle(image,cv::Point(i%image.step,i/image.step),5,cv::Scalar(255,0,0)); 140 | } 141 | } 142 | }; 143 | 144 | 145 | #endif 146 | -------------------------------------------------------------------------------- /Chapter05/morphology.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 5 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | int main() 24 | { 25 | // Read input image 26 | cv::Mat image= cv::imread("binary.bmp"); 27 | if (!image.data) 28 | return 0; 29 | 30 | // Display the image 31 | cv::namedWindow("Image"); 32 | cv::imshow("Image",image); 33 | 34 | // Erode the image 35 | cv::Mat eroded; 36 | cv::erode(image,eroded,cv::Mat()); 37 | 38 | // Display the eroded image 39 | cv::namedWindow("Eroded Image"); 40 | cv::imshow("Eroded Image",eroded); 41 | 42 | // Dilate the image 43 | cv::Mat dilated; 44 | cv::dilate(image,dilated,cv::Mat()); 45 | 46 | // Display the dialted image 47 | cv::namedWindow("Dilated Image"); 48 | cv::imshow("Dilated Image",dilated); 49 | 50 | // Erode the image with a larger s.e. 51 | cv::Mat element(7,7,CV_8U,cv::Scalar(1)); 52 | cv::erode(image,eroded,element); 53 | 54 | // Display the eroded image 55 | cv::namedWindow("Eroded Image (7x7)"); 56 | cv::imshow("Eroded Image (7x7)",eroded); 57 | 58 | // Erode the image 3 times. 59 | cv::erode(image,eroded,cv::Mat(),cv::Point(-1,-1),3); 60 | 61 | // Display the eroded image 62 | cv::namedWindow("Eroded Image (3 times)"); 63 | cv::imshow("Eroded Image (3 times)",eroded); 64 | 65 | // Close the image 66 | cv::Mat element5(5,5,CV_8U,cv::Scalar(1)); 67 | cv::Mat closed; 68 | cv::morphologyEx(image,closed,cv::MORPH_CLOSE,element5); 69 | 70 | // Display the opened image 71 | cv::namedWindow("Closed Image"); 72 | cv::imshow("Closed Image",closed); 73 | 74 | // Open the image 75 | cv::Mat opened; 76 | cv::morphologyEx(image,opened,cv::MORPH_OPEN,element5); 77 | 78 | // Display the opened image 79 | cv::namedWindow("Opened Image"); 80 | cv::imshow("Opened Image",opened); 81 | 82 | // Close and Open the image 83 | cv::morphologyEx(image,image,cv::MORPH_CLOSE,element5); 84 | cv::morphologyEx(image,image,cv::MORPH_OPEN,element5); 85 | 86 | // Display the close/opened image 87 | cv::namedWindow("Closed and Opened Image"); 88 | cv::imshow("Closed and Opened Image",image); 89 | cv::imwrite("binaryGroup.bmp",image); 90 | 91 | // Read input image 92 | image= cv::imread("binary.bmp"); 93 | 94 | // Open and Close the image 95 | cv::morphologyEx(image,image,cv::MORPH_OPEN,element5); 96 | cv::morphologyEx(image,image,cv::MORPH_CLOSE,element5); 97 | 98 | // Display the close/opened image 99 | cv::namedWindow("Opened and Closed Image"); 100 | cv::imshow("Opened and Closed Image",image); 101 | 102 | cv::waitKey(); 103 | return 0; 104 | } 105 | 106 | -------------------------------------------------------------------------------- /Chapter05/mserFeatures.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 5 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2010-2011 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "mserFeatures.h" 27 | 28 | int main() 29 | { 30 | // Read input image 31 | cv::Mat image= cv::imread("building.jpg",0); 32 | if (!image.data) 33 | return 0; 34 | // resize for book printing 35 | cv::resize(image, image, cv::Size(), 0.7, 0.7); 36 | 37 | // Display the image 38 | cv::namedWindow("Image"); 39 | cv::imshow("Image",image); 40 | 41 | 42 | // basic MSER detector 43 | cv::MSER mser(5, // delta value for local minima detection 44 | 200, // min acceptable area 45 | 1500); // max acceptable area 46 | 47 | // vector of point sets 48 | std::vector > points; 49 | // detect MSER features 50 | mser(image, points); 51 | 52 | std::cout << points.size() << " MSERs detected" << std::endl; 53 | 54 | // create white image 55 | cv::Mat output(image.size(),CV_8UC3); 56 | output= cv::Scalar(255,255,255); 57 | 58 | // random number generator 59 | cv::RNG rng; 60 | 61 | // for each detected feature 62 | for (std::vector >::iterator it= points.begin(); 63 | it!= points.end(); ++it) { 64 | 65 | // generate a random color 66 | cv::Vec3b c(rng.uniform(0,255), 67 | rng.uniform(0,255), 68 | rng.uniform(0,255)); 69 | 70 | std::cout << "MSER size= " << it->size() << std::endl; 71 | 72 | // for each point in MSER set 73 | for (std::vector::iterator itPts= it->begin(); 74 | itPts!= it->end(); ++itPts) { 75 | 76 | //do not overwrite MSER pixels 77 | if (output.at(*itPts)[0]==255) { 78 | 79 | output.at(*itPts)= c; 80 | } 81 | } 82 | } 83 | 84 | cv::namedWindow("MSER point sets"); 85 | cv::imshow("MSER point sets",output); 86 | cv::imwrite("mser.bmp", output); 87 | 88 | // detection using mserFeatures class 89 | 90 | // create MSER feature detector instance 91 | MSERFeatures mserF(200, // min area 92 | 1500, // max area 93 | 0.5); // ratio area threshold 94 | // default delta is used 95 | 96 | // the vector of bounding rotated rectangles 97 | std::vector rects; 98 | 99 | // detect and get the image 100 | cv::Mat result= mserF.getImageOfEllipses(image,rects); 101 | 102 | // display detected MSER 103 | cv::namedWindow("MSER regions"); 104 | cv::imshow("MSER regions",result); 105 | 106 | cv::waitKey(); 107 | } 108 | -------------------------------------------------------------------------------- /Chapter05/mserFeatures.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 5 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #if !defined MSERF 20 | #define MSERF 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | class MSERFeatures { 29 | 30 | private: 31 | 32 | cv::MSER mser; // mser detector 33 | double minAreaRatio; // extra rejection parameter 34 | 35 | public: 36 | 37 | MSERFeatures(int minArea=60, int maxArea=14400, // aceptable size range 38 | double minAreaRatio=0.5, // min value for MSER area/bounding-rect area 39 | int delta=5, // delta value used for stability measure 40 | double maxVariation=0.25, // max allowed area variation 41 | double minDiversity=0.2) // min size increase between child and parent 42 | : mser(delta,minArea,maxArea,maxVariation,minDiversity), 43 | minAreaRatio(minAreaRatio) {} 44 | 45 | // get the rotated bouding rectangles corresponding to each MSER feature 46 | // if (mser area / bounding rect area) < areaRatio, the feature is rejected 47 | void getBoundingRects(const cv::Mat &image, std::vector &rects) { 48 | 49 | // detect MSER features 50 | std::vector > points; 51 | mser(image, points); 52 | 53 | // for each detected feature 54 | for (std::vector >::iterator it= points.begin(); 55 | it!= points.end(); ++it) { 56 | 57 | // Extract bouding rectangles 58 | cv::RotatedRect rr= cv::minAreaRect(*it); 59 | 60 | // check area ratio 61 | if (it->size() > minAreaRatio*rr.size.area()) 62 | rects.push_back(rr); 63 | } 64 | } 65 | 66 | // draw the rotated ellipses corresponding to each MSER feature 67 | cv::Mat getImageOfEllipses(const cv::Mat &image, std::vector &rects, cv::Scalar color=255) { 68 | 69 | // image on which to draw 70 | cv::Mat output= image.clone(); 71 | 72 | // get the MSER features 73 | getBoundingRects(image, rects); 74 | 75 | // for each detected feature 76 | for (std::vector::iterator it= rects.begin(); 77 | it!= rects.end(); ++it) { 78 | 79 | cv::ellipse(output,*it,color); 80 | } 81 | 82 | return output; 83 | } 84 | 85 | double getAreaRatio() { 86 | 87 | return minAreaRatio; 88 | } 89 | 90 | void setAreaRatio(double ratio) { 91 | 92 | minAreaRatio= ratio; 93 | } 94 | }; 95 | 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /Chapter05/segment.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 5 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "watershedSegmentation.h" 24 | 25 | 26 | int main() 27 | { 28 | // Read input image 29 | cv::Mat image= cv::imread("group.jpg"); 30 | if (!image.data) 31 | return 0; 32 | // resize for book printing 33 | cv::resize(image, image, cv::Size(), 0.7, 0.7); 34 | std::cout << image.rows << "," << image.cols << std::endl; 35 | 36 | // Display the image 37 | cv::namedWindow("Original Image"); 38 | cv::imshow("Original Image",image); 39 | 40 | // Get the binary map 41 | cv::Mat binary; 42 | binary= cv::imread("binary.bmp",0); 43 | 44 | // Display the binary image 45 | cv::namedWindow("Binary Image"); 46 | cv::imshow("Binary Image",binary); 47 | 48 | // Eliminate noise and smaller objects 49 | cv::Mat fg; 50 | cv::erode(binary,fg,cv::Mat(),cv::Point(-1,-1),4); 51 | 52 | // Display the foreground image 53 | cv::namedWindow("Foreground Image"); 54 | cv::imshow("Foreground Image",fg); 55 | 56 | // Identify image pixels without objects 57 | cv::Mat bg; 58 | cv::dilate(binary,bg,cv::Mat(),cv::Point(-1,-1),4); 59 | cv::threshold(bg,bg,1,128,cv::THRESH_BINARY_INV); 60 | 61 | // Display the background image 62 | cv::namedWindow("Background Image"); 63 | cv::imshow("Background Image",bg); 64 | 65 | // Show markers image 66 | cv::Mat markers(binary.size(),CV_8U,cv::Scalar(0)); 67 | markers= fg+bg; 68 | cv::namedWindow("Markers"); 69 | cv::imshow("Markers",markers); 70 | 71 | // Create watershed segmentation object 72 | WatershedSegmenter segmenter; 73 | 74 | // Set markers and process 75 | segmenter.setMarkers(markers); 76 | segmenter.process(image); 77 | 78 | // Display segmentation result 79 | cv::namedWindow("Segmentation"); 80 | cv::imshow("Segmentation",segmenter.getSegmentation()); 81 | 82 | // Display watersheds 83 | cv::namedWindow("Watersheds"); 84 | cv::imshow("Watersheds",segmenter.getWatersheds()); 85 | 86 | // Open another image 87 | image= cv::imread("tower.jpg"); 88 | // resize for book printing 89 | cv::resize(image, image, cv::Size(), 0.6, 0.6); 90 | 91 | // Identify background pixels 92 | cv::Mat imageMask(image.size(),CV_8U,cv::Scalar(0)); 93 | cv::rectangle(imageMask,cv::Point(5,5),cv::Point(image.cols-5,image.rows-5),cv::Scalar(255),3); 94 | // Identify foreground pixels (in the middle of the image) 95 | cv::rectangle(imageMask,cv::Point(image.cols/2-10,image.rows/2-10), 96 | cv::Point(image.cols/2+10,image.rows/2+10),cv::Scalar(1),10); 97 | 98 | // Set markers and process 99 | segmenter.setMarkers(imageMask); 100 | segmenter.process(image); 101 | 102 | // Display the image with markers 103 | cv::rectangle(image,cv::Point(5,5),cv::Point(image.cols-5,image.rows-5),cv::Scalar(255,255,255),3); 104 | cv::rectangle(image,cv::Point(image.cols/2-10,image.rows/2-10), 105 | cv::Point(image.cols/2+10,image.rows/2+10),cv::Scalar(1,1,1),10); 106 | cv::namedWindow("Image with marker"); 107 | cv::imshow("Image with marker",image); 108 | 109 | // Display watersheds 110 | cv::namedWindow("Watersheds of foreground object"); 111 | cv::imshow("Watersheds of foreground object",segmenter.getWatersheds()); 112 | 113 | // Open another image 114 | image= cv::imread("tower.jpg"); 115 | 116 | // define bounding rectangle 117 | cv::Rect rectangle(50,70,image.cols-150,image.rows-180); 118 | 119 | cv::Mat result; // segmentation result (4 possible values) 120 | cv::Mat bgModel,fgModel; // the models (internally used) 121 | // GrabCut segmentation 122 | cv::grabCut(image, // input image 123 | result, // segmentation result 124 | rectangle,// rectangle containing foreground 125 | bgModel,fgModel, // models 126 | 1, // number of iterations 127 | cv::GC_INIT_WITH_RECT); // use rectangle 128 | 129 | // Get the pixels marked as likely foreground 130 | cv::compare(result,cv::GC_PR_FGD,result,cv::CMP_EQ); 131 | // Generate output image 132 | cv::Mat foreground(image.size(),CV_8UC3,cv::Scalar(255,255,255)); 133 | image.copyTo(foreground,result); // bg pixels not copied 134 | 135 | // draw rectangle on original image 136 | cv::rectangle(image, rectangle, cv::Scalar(255,255,255),1); 137 | cv::namedWindow("Image"); 138 | cv::imshow("Image",image); 139 | 140 | // display result 141 | cv::namedWindow("Segmented Image"); 142 | cv::imshow("Segmented Image",foreground); 143 | 144 | // Open another image 145 | image= cv::imread("group.jpg"); 146 | // resize for book printing 147 | cv::resize(image, image, cv::Size(), 0.7, 0.7); 148 | 149 | // define bounding rectangle 150 | cv::Rect rectangle2(5,70,260,120); 151 | cv::Mat bkgModel,fgrModel; // the models (internally used) 152 | // GrabCut segmentation 153 | cv::grabCut(image, // input image 154 | result, // segmentation result 155 | rectangle2,bkgModel,fgrModel,5,cv::GC_INIT_WITH_RECT); 156 | // Get the pixels marked as likely foreground 157 | // cv::compare(result,cv::GC_PR_FGD,result,cv::CMP_EQ); 158 | result= result&1; 159 | foreground.create(image.size(),CV_8UC3); 160 | foreground.setTo(cv::Scalar(255,255,255)); 161 | image.copyTo(foreground,result); // bg pixels not copied 162 | 163 | // draw rectangle on original image 164 | cv::rectangle(image, rectangle2, cv::Scalar(255,255,255),1); 165 | cv::namedWindow("Image with rectangle"); 166 | cv::imshow("Image with rectangle",image); 167 | 168 | // display result 169 | cv::namedWindow("Foreground objects"); 170 | cv::imshow("Foreground objects",foreground); 171 | 172 | cv::waitKey(); 173 | return 0; 174 | } 175 | -------------------------------------------------------------------------------- /Chapter05/watershedSegmentation.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 5 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library. 4 | by Robert Laganiere, Packt Publishing, 2011. 5 | 6 | This program is free software; permission is hereby granted to use, copy, modify, 7 | and distribute this source code, or portions thereof, for any purpose, without fee, 8 | subject to the restriction that the copyright notice may not be removed 9 | or altered from any source or altered source distribution. 10 | The software is released on an as-is basis and without any warranties of any kind. 11 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 12 | The author disclaims all warranties with regard to this software, any use, 13 | and any consequent failure, is purely the responsibility of the user. 14 | 15 | Copyright (C) 2010-2011 Robert Laganiere, www.laganiere.name 16 | \*------------------------------------------------------------------------------------------*/ 17 | 18 | #if !defined WATERSHS 19 | #define WATERSHS 20 | 21 | #include 22 | #include 23 | 24 | class WatershedSegmenter { 25 | 26 | private: 27 | 28 | cv::Mat markers; 29 | 30 | public: 31 | 32 | void setMarkers(const cv::Mat& markerImage) { 33 | 34 | // Convert to image of ints 35 | markerImage.convertTo(markers,CV_32S); 36 | } 37 | 38 | cv::Mat process(const cv::Mat &image) { 39 | 40 | // Apply watershed 41 | cv::watershed(image,markers); 42 | 43 | return markers; 44 | } 45 | 46 | // Return result in the form of an image 47 | cv::Mat getSegmentation() { 48 | 49 | cv::Mat tmp; 50 | // all segment with label higher than 255 51 | // will be assigned value 255 52 | markers.convertTo(tmp,CV_8U); 53 | 54 | return tmp; 55 | } 56 | 57 | // Return watershed in the form of an image 58 | cv::Mat getWatersheds() { 59 | 60 | cv::Mat tmp; 61 | markers.convertTo(tmp,CV_8U,255,255); 62 | 63 | return tmp; 64 | } 65 | }; 66 | 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /Chapter06/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # cmake for OpenCV2 Cookbook 2 | # your opencv/build directory should be in your system PATH 3 | 4 | # set minimum required version for cmake 5 | cmake_minimum_required(VERSION 2.8) 6 | 7 | # define the project name 8 | set(project_name "Chapter06") 9 | 10 | # set the project namee 11 | project("${project_name}") 12 | 13 | # add opencv package to the project 14 | find_package( OpenCV REQUIRED ) 15 | MESSAGE("OpenCV version : ${OpenCV_VERSION}") 16 | 17 | # add opencv include directories to the project 18 | include_directories( ${OpenCV_INCLUDE_DIRS} ) 19 | 20 | # add executable 21 | add_executable( derivatives derivatives.cpp) 22 | add_executable( filters filters.cpp) 23 | 24 | # link libraries 25 | target_link_libraries( derivatives ${OpenCV_LIBS}) 26 | target_link_libraries( filters ${OpenCV_LIBS}) 27 | 28 | -------------------------------------------------------------------------------- /Chapter06/README.txt: -------------------------------------------------------------------------------- 1 | This directory contains material supporting chapter 6 of the cookbook: 2 | Computer Vision Programming using the OpenCV Library. 3 | Second Edition 4 | by Robert Laganiere, Packt Publishing, 2013. 5 | 6 | File: 7 | filters.cpp 8 | correspond to Recipes: 9 | Filtering Images using Low-pass Filters 10 | Filtering Images using a Median Filter 11 | 12 | Files: 13 | derivatives.cpp 14 | laplacianZC.h 15 | correspond to Recipes: 16 | Applying Directional Filters to Detect Edges 17 | Computing the Laplacian of an Image 18 | 19 | You need the images: 20 | boldt.jpg 21 | salted.bmp 22 | -------------------------------------------------------------------------------- /Chapter06/laplacianZC.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 6 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #if !defined LAPLACEZC 20 | #define LAPLACEZC 21 | 22 | #include 23 | #include 24 | 25 | class LaplacianZC { 26 | 27 | private: 28 | // laplacian 29 | cv::Mat laplace; 30 | 31 | // Aperture size of the laplacian kernel 32 | int aperture; 33 | 34 | public: 35 | 36 | LaplacianZC() : aperture(3) {} 37 | 38 | // Set the aperture size of the kernel 39 | void setAperture(int a) { 40 | 41 | aperture= a; 42 | } 43 | 44 | // Get the aperture size of the kernel 45 | int getAperture() const { 46 | 47 | return aperture; 48 | } 49 | 50 | // Compute the floating point Laplacian 51 | cv::Mat computeLaplacian(const cv::Mat& image) { 52 | 53 | // Compute Laplacian 54 | cv::Laplacian(image,laplace,CV_32F,aperture); 55 | 56 | return laplace; 57 | } 58 | 59 | // Get the Laplacian result in 8-bit image 60 | // zero corresponds to gray level 128 61 | // if no scale is provided, then the max value will be 62 | // scaled to intensity 255 63 | // You must call computeLaplacian before calling this method 64 | cv::Mat getLaplacianImage(double scale=-1.0) { 65 | 66 | if (scale<0) { 67 | 68 | double lapmin, lapmax; 69 | cv::minMaxLoc(laplace,&lapmin,&lapmax); 70 | 71 | scale= 127/ std::max(-lapmin,lapmax); 72 | } 73 | 74 | cv::Mat laplaceImage; 75 | laplace.convertTo(laplaceImage,CV_8U,scale,128); 76 | 77 | return laplaceImage; 78 | } 79 | 80 | // Get a binary image of the zero-crossings 81 | // laplacian image should be CV_32F 82 | cv::Mat getZeroCrossings(cv::Mat laplace) { 83 | 84 | // threshold at 0 85 | // negative values in black 86 | // positive values in white 87 | cv::Mat signImage; 88 | cv::threshold(laplace,signImage,0,255,cv::THRESH_BINARY); 89 | 90 | // convert the +/- image into CV_8U 91 | cv::Mat binary; 92 | signImage.convertTo(binary,CV_8U); 93 | 94 | // dilate the binary image of +/- regions 95 | cv::Mat dilated; 96 | cv::dilate(binary,dilated,cv::Mat()); 97 | 98 | // return the zero-crossing contours 99 | return dilated-binary; 100 | } 101 | }; 102 | 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /Chapter07/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # cmake for OpenCV2 Cookbook 2 | # your opencv/build directory should be in your system PATH 3 | 4 | # set minimum required version for cmake 5 | cmake_minimum_required(VERSION 2.8) 6 | 7 | # define the project name 8 | set(project_name "Chapter07") 9 | 10 | # set the project namee 11 | project("${project_name}") 12 | 13 | # add opencv package to the project 14 | find_package( OpenCV REQUIRED ) 15 | MESSAGE("OpenCV version : ${OpenCV_VERSION}") 16 | 17 | # add opencv include directories to the project 18 | include_directories( ${OpenCV_INCLUDE_DIRS} ) 19 | 20 | # add executable 21 | add_executable( blobs blobs.cpp) 22 | add_executable( contours contours.cpp) 23 | 24 | # link libraries 25 | target_link_libraries( blobs ${OpenCV_LIBS}) 26 | target_link_libraries( contours ${OpenCV_LIBS}) 27 | 28 | -------------------------------------------------------------------------------- /Chapter07/README.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laganiere/OpenCV2Cookbook2ndEd/986f6e92f561b7d7871b063aab7e3e91ed9d6ea8/Chapter07/README.txt -------------------------------------------------------------------------------- /Chapter07/blobs.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 7 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | int main() 26 | { 27 | // Read input binary image 28 | cv::Mat image= cv::imread("binaryGroup.bmp",0); 29 | if (!image.data) 30 | return 0; 31 | 32 | cv::namedWindow("Binary Image"); 33 | cv::imshow("Binary Image",image); 34 | 35 | // Get the contours of the connected components 36 | std::vector > contours; 37 | cv::findContours(image, 38 | contours, // a vector of contours 39 | CV_RETR_EXTERNAL, // retrieve the external contours 40 | CV_CHAIN_APPROX_NONE); // retrieve all pixels of each contours 41 | 42 | // Print contours' length 43 | std::cout << "Contours: " << contours.size() << std::endl; 44 | std::vector >::const_iterator itContours= contours.begin(); 45 | for ( ; itContours!=contours.end(); ++itContours) { 46 | 47 | std::cout << "Size: " << itContours->size() << std::endl; 48 | } 49 | 50 | // draw black contours on white image 51 | cv::Mat result(image.size(),CV_8U,cv::Scalar(255)); 52 | cv::drawContours(result,contours, 53 | -1, // draw all contours 54 | cv::Scalar(0), // in black 55 | 2); // with a thickness of 2 56 | 57 | cv::namedWindow("Contours"); 58 | cv::imshow("Contours",result); 59 | 60 | // Eliminate too short or too long contours 61 | int cmin= 50; // minimum contour length 62 | int cmax= 1000; // maximum contour length 63 | std::vector >::iterator itc= contours.begin(); 64 | while (itc!=contours.end()) { 65 | 66 | if (itc->size() < cmin || itc->size() > cmax) 67 | itc= contours.erase(itc); 68 | else 69 | ++itc; 70 | } 71 | 72 | // draw contours on the original image 73 | cv::Mat original= cv::imread("group.jpg"); 74 | // image is resize for book printing 75 | cv::resize(original, original, cv::Size(), 0.7, 0.7); 76 | 77 | cv::drawContours(original,contours, 78 | -1, // draw all contours 79 | cv::Scalar(255,255,255), // in white 80 | 2); // with a thickness of 2 81 | 82 | cv::namedWindow("Contours on Animals"); 83 | cv::imshow("Contours on Animals",original); 84 | 85 | // Let's now draw black contours on white image 86 | result.setTo(cv::Scalar(255)); 87 | cv::drawContours(result,contours, 88 | -1, // draw all contours 89 | 0, // in black 90 | 1); // with a thickness of 1 91 | 92 | image= cv::imread("binaryGroup.bmp",0); 93 | 94 | // testing the bounding box 95 | cv::Rect r0= cv::boundingRect(contours[0]); 96 | // draw the rectangle 97 | cv::rectangle(result,r0, 0, 2); 98 | 99 | // testing the enclosing circle 100 | float radius; 101 | cv::Point2f center; 102 | cv::minEnclosingCircle(contours[1],center,radius); 103 | // draw the cricle 104 | cv::circle(result,center,static_cast(radius), 0, 2); 105 | 106 | // testing the approximate polygon 107 | std::vector poly; 108 | cv::approxPolyDP(contours[2],poly,5,true); 109 | // draw the polygon 110 | cv::polylines(result, poly, true, 0, 2); 111 | 112 | std::cout << "Polygon size: " << poly.size() << std::endl; 113 | 114 | // testing the convex hull 115 | std::vector hull; 116 | cv::convexHull(contours[3],hull); 117 | // draw the polygon 118 | cv::polylines(result, hull, true, 0, 2); 119 | 120 | std::vector defects; 121 | // cv::convexityDefects(contours[3], hull, defects); 122 | 123 | // testing the moments 124 | 125 | // iterate over all contours 126 | itc= contours.begin(); 127 | while (itc!=contours.end()) { 128 | 129 | // compute all moments 130 | cv::Moments mom= cv::moments(*itc++); 131 | 132 | // draw mass center 133 | cv::circle(result, 134 | // position of mass center converted to integer 135 | cv::Point(mom.m10/mom.m00,mom.m01/mom.m00), 136 | 2,cv::Scalar(0),2); // draw black dot 137 | } 138 | 139 | cv::namedWindow("Some Shape descriptors"); 140 | cv::imshow("Some Shape descriptors",result); 141 | 142 | // New call to findContours but with CV_RETR_LIST flag 143 | image= cv::imread("binaryGroup.bmp",0); 144 | 145 | // Get the contours of the connected components 146 | cv::findContours(image, 147 | contours, // a vector of contours 148 | CV_RETR_LIST, // retrieve the external and internal contours 149 | CV_CHAIN_APPROX_NONE); // retrieve all pixels of each contours 150 | 151 | // draw black contours on white image 152 | result.setTo(255); 153 | cv::drawContours(result,contours, 154 | -1, // draw all contours 155 | 0, // in black 156 | 2); // with a thickness of 2 157 | cv::namedWindow("All Contours"); 158 | cv::imshow("All Contours",result); 159 | 160 | // get a MSER image 161 | cv::Mat components; 162 | components= cv::imread("mser.bmp",0); 163 | 164 | // create a binary version 165 | components= components==255; 166 | // open the image (white background) 167 | cv::morphologyEx(components,components,cv::MORPH_OPEN,cv::Mat(),cv::Point(-1,-1),3); 168 | 169 | cv::namedWindow("MSER image"); 170 | cv::imshow("MSER image",components); 171 | 172 | contours.clear(); 173 | //invert image (background must be black) 174 | cv::Mat componentsInv= 255-components; 175 | // Get the contours of the connected components 176 | cv::findContours(componentsInv, 177 | contours, // a vector of contours 178 | CV_RETR_EXTERNAL, // retrieve the external contours 179 | CV_CHAIN_APPROX_NONE); // retrieve all pixels of each contours 180 | 181 | // white image 182 | cv::Mat quadri(components.size(),CV_8U,255); 183 | 184 | // for all contours 185 | std::vector >::iterator it= contours.begin(); 186 | while (it!= contours.end()) { 187 | poly.clear(); 188 | // approximate contour by polygon 189 | cv::approxPolyDP(*it,poly,5,true); 190 | 191 | // do we have a quadrilateral? 192 | if (poly.size()==4) { 193 | // draw it 194 | cv::polylines(quadri, poly, true, 0, 2); 195 | } 196 | 197 | ++it; 198 | } 199 | 200 | cv::namedWindow("MSER quadrilateral"); 201 | cv::imshow("MSER quadrilateral",quadri); 202 | 203 | cv::waitKey(); 204 | return 0; 205 | } 206 | -------------------------------------------------------------------------------- /Chapter07/edgedetector.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 7 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #if !defined SOBELEDGES 20 | #define SOBELEDGES 21 | 22 | #define PI 3.1415926 23 | 24 | #include 25 | #include 26 | 27 | class EdgeDetector { 28 | 29 | private: 30 | 31 | // original image 32 | cv::Mat img; 33 | 34 | // 16-bit signed int image 35 | cv::Mat sobel; 36 | 37 | // Aperture size of the Sobel kernel 38 | int aperture; 39 | 40 | // Sobel magnitude 41 | cv::Mat sobelMagnitude; 42 | 43 | // Sobel orientation 44 | cv::Mat sobelOrientation; 45 | 46 | public: 47 | 48 | EdgeDetector() : aperture(3) {} 49 | 50 | // Set the aperture size of the kernel 51 | void setAperture(int a) { 52 | 53 | aperture= a; 54 | } 55 | 56 | // Get the aperture size of the kernel 57 | int getAperture() const { 58 | 59 | return aperture; 60 | } 61 | 62 | // Compute the Sobel 63 | void computeSobel(const cv::Mat& image) { 64 | 65 | cv::Mat sobelX; 66 | cv::Mat sobelY; 67 | 68 | // Compute Sobel 69 | cv::Sobel(image, sobelX, CV_32F, 1, 0, aperture); 70 | cv::Sobel(image, sobelY, CV_32F, 0, 1, aperture); 71 | 72 | // Compute magnitude and orientation 73 | cv::cartToPolar(sobelX, sobelY, sobelMagnitude, sobelOrientation); 74 | } 75 | 76 | // Compute the Sobel 77 | void computeSobel(const cv::Mat& image, cv::Mat &sobelX, cv::Mat &sobelY) { 78 | 79 | // Compute Sobel 80 | cv::Sobel(image, sobelX, CV_32F, 1, 0, aperture); 81 | cv::Sobel(image, sobelY, CV_32F, 0, 1, aperture); 82 | 83 | // Compute magnitude and orientation 84 | cv::cartToPolar(sobelX, sobelY, sobelMagnitude, sobelOrientation); 85 | } 86 | 87 | // Get Sobel magnitude 88 | cv::Mat getMagnitude() { 89 | 90 | return sobelMagnitude; 91 | } 92 | 93 | // Get Sobel orientation 94 | cv::Mat getOrientation() { 95 | 96 | return sobelOrientation; 97 | } 98 | 99 | // Get a thresholded binary map 100 | cv::Mat getBinaryMap(double threshold) { 101 | 102 | cv::Mat bin; 103 | cv::threshold(sobelMagnitude,bin,threshold,255,cv::THRESH_BINARY_INV); 104 | 105 | return bin; 106 | } 107 | 108 | // Get a CV_8U image of the Sobel 109 | cv::Mat getSobelImage() { 110 | 111 | cv::Mat bin; 112 | 113 | double minval, maxval; 114 | cv::minMaxLoc(sobelMagnitude,&minval,&maxval); 115 | sobelMagnitude.convertTo(bin,CV_8U,255/maxval); 116 | 117 | return bin; 118 | } 119 | 120 | // Get a CV_8U image of the Sobel orientation 121 | // 1 gray-level = 2 degrees 122 | cv::Mat getSobelOrientationImage() { 123 | 124 | cv::Mat bin; 125 | 126 | sobelOrientation.convertTo(bin,CV_8U,90/PI); 127 | 128 | return bin; 129 | } 130 | 131 | }; 132 | 133 | 134 | #endif 135 | -------------------------------------------------------------------------------- /Chapter07/linefinder.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 7 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #if !defined LINEF 20 | #define LINEF 21 | 22 | #include 23 | #include 24 | #define PI 3.1415926 25 | 26 | class LineFinder { 27 | 28 | private: 29 | 30 | // original image 31 | cv::Mat img; 32 | 33 | // vector containing the end points 34 | // of the detected lines 35 | std::vector lines; 36 | 37 | // accumulator resolution parameters 38 | double deltaRho; 39 | double deltaTheta; 40 | 41 | // minimum number of votes that a line 42 | // must receive before being considered 43 | int minVote; 44 | 45 | // min length for a line 46 | double minLength; 47 | 48 | // max allowed gap along the line 49 | double maxGap; 50 | 51 | public: 52 | 53 | // Default accumulator resolution is 1 pixel by 1 degree 54 | // no gap, no mimimum length 55 | LineFinder() : deltaRho(1), deltaTheta(PI/180), minVote(10), minLength(0.), maxGap(0.) {} 56 | 57 | // Set the resolution of the accumulator 58 | void setAccResolution(double dRho, double dTheta) { 59 | 60 | deltaRho= dRho; 61 | deltaTheta= dTheta; 62 | } 63 | 64 | // Set the minimum number of votes 65 | void setMinVote(int minv) { 66 | 67 | minVote= minv; 68 | } 69 | 70 | // Set line length and gap 71 | void setLineLengthAndGap(double length, double gap) { 72 | 73 | minLength= length; 74 | maxGap= gap; 75 | } 76 | 77 | // Apply probabilistic Hough Transform 78 | std::vector findLines(cv::Mat& binary) { 79 | 80 | lines.clear(); 81 | cv::HoughLinesP(binary,lines,deltaRho,deltaTheta,minVote, minLength, maxGap); 82 | 83 | return lines; 84 | } 85 | 86 | // Draw the detected lines on an image 87 | void drawDetectedLines(cv::Mat &image, cv::Scalar color=cv::Scalar(255,255,255)) { 88 | 89 | // Draw the lines 90 | std::vector::const_iterator it2= lines.begin(); 91 | 92 | while (it2!=lines.end()) { 93 | 94 | cv::Point pt1((*it2)[0],(*it2)[1]); 95 | cv::Point pt2((*it2)[2],(*it2)[3]); 96 | 97 | cv::line( image, pt1, pt2, color); 98 | 99 | ++it2; 100 | } 101 | } 102 | 103 | // Eliminates lines that do not have an orientation equals to 104 | // the ones specified in the input matrix of orientations 105 | // At least the given percentage of pixels on the line must 106 | // be within plus or minus delta of the corresponding orientation 107 | std::vector removeLinesOfInconsistentOrientations( 108 | const cv::Mat &orientations, double percentage, double delta) { 109 | 110 | std::vector::iterator it= lines.begin(); 111 | 112 | // check all lines 113 | while (it!=lines.end()) { 114 | 115 | // end points 116 | int x1= (*it)[0]; 117 | int y1= (*it)[1]; 118 | int x2= (*it)[2]; 119 | int y2= (*it)[3]; 120 | 121 | // line orientation + 90o to get the parallel line 122 | double ori1= atan2(static_cast(y1-y2),static_cast(x1-x2))+PI/2; 123 | if (ori1>PI) ori1= ori1-2*PI; 124 | 125 | double ori2= atan2(static_cast(y2-y1),static_cast(x2-x1))+PI/2; 126 | if (ori2>PI) ori2= ori2-2*PI; 127 | 128 | // for all points on the line 129 | cv::LineIterator lit(orientations,cv::Point(x1,y1),cv::Point(x2,y2)); 130 | int i,count=0; 131 | for(i = 0, count=0; i < lit.count; i++, ++lit) { 132 | 133 | float ori= *(reinterpret_cast(*lit)); 134 | 135 | // is line orientation similar to gradient orientation ? 136 | if (std::min(fabs(ori-ori1),fabs(ori-ori2))(i); 142 | 143 | // set to zero lines of inconsistent orientation 144 | if (consistency < percentage) { 145 | 146 | (*it)[0]=(*it)[1]=(*it)[2]=(*it)[3]=0; 147 | 148 | } 149 | 150 | ++it; 151 | } 152 | 153 | return lines; 154 | } 155 | }; 156 | 157 | 158 | #endif 159 | -------------------------------------------------------------------------------- /Chapter08/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # cmake for OpenCV2 Cookbook 2 | # your opencv/build directory should be in your system PATH 3 | 4 | # set minimum required version for cmake 5 | cmake_minimum_required(VERSION 2.8) 6 | 7 | # define the project name 8 | set(project_name "Chapter08") 9 | 10 | # set the project namee 11 | project("${project_name}") 12 | 13 | # add opencv package to the project 14 | find_package( OpenCV REQUIRED ) 15 | MESSAGE("OpenCV version : ${OpenCV_VERSION}") 16 | 17 | # add opencv include directories to the project 18 | include_directories( ${OpenCV_INCLUDE_DIRS} ) 19 | 20 | # add executable 21 | add_executable( interestPoints interestPoints.cpp) 22 | 23 | # link libraries 24 | target_link_libraries( interestPoints ${OpenCV_LIBS}) 25 | 26 | -------------------------------------------------------------------------------- /Chapter08/README.txt: -------------------------------------------------------------------------------- 1 | This directory contains material supporting chapter 8 of the cookbook: 2 | Computer Vision Programming using the OpenCV Library. 3 | Second Edition 4 | 5 | 6 | by Robert Laganiere, Packt Publishing, 2013. 7 | 8 | Files: 9 | harrisDetector.h 10 | interestPoints.cpp 11 | correspond to Recipes: 12 | Detecting Corners in images 13 | Detecting features very fast 14 | Detecting Scale-Invariant Features 15 | Detecting fast features at multiple scales 16 | 17 | You need the images: 18 | church01.jpg 19 | church02.jpg 20 | church03.jpg 21 | -------------------------------------------------------------------------------- /Chapter08/harrisDetector.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 8 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #if !defined HARRISD 20 | #define HARRISD 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | class HarrisDetector { 29 | 30 | private: 31 | 32 | // 32-bit float image of corner strength 33 | cv::Mat cornerStrength; 34 | // 32-bit float image of thresholded corners 35 | cv::Mat cornerTh; 36 | // image of local maxima (internal) 37 | cv::Mat localMax; 38 | // size of neighbourhood for derivatives smoothing 39 | int neighbourhood; 40 | // aperture for gradient computation 41 | int aperture; 42 | // Harris parameter 43 | double k; 44 | // maximum strength for threshold computation 45 | double maxStrength; 46 | // calculated threshold (internal) 47 | double threshold; 48 | // size of neighbourhood for non-max suppression 49 | int nonMaxSize; 50 | // kernel for non-max suppression 51 | cv::Mat kernel; 52 | 53 | public: 54 | 55 | HarrisDetector() : neighbourhood(3), aperture(3), k(0.1), maxStrength(0.0), threshold(0.01), nonMaxSize(3) { 56 | 57 | setLocalMaxWindowSize(nonMaxSize); 58 | } 59 | 60 | // Create kernel used in non-maxima suppression 61 | void setLocalMaxWindowSize(int size) { 62 | 63 | nonMaxSize= size; 64 | kernel.create(nonMaxSize,nonMaxSize,CV_8U); 65 | } 66 | 67 | // Compute Harris corners 68 | void detect(const cv::Mat& image) { 69 | 70 | // Harris computation 71 | cv::cornerHarris(image,cornerStrength, 72 | neighbourhood,// neighborhood size 73 | aperture, // aperture size 74 | k); // Harris parameter 75 | 76 | // internal threshold computation 77 | cv::minMaxLoc(cornerStrength,0,&maxStrength); 78 | 79 | // local maxima detection 80 | cv::Mat dilated; // temporary image 81 | cv::dilate(cornerStrength,dilated,cv::Mat()); 82 | cv::compare(cornerStrength,dilated,localMax,cv::CMP_EQ); 83 | } 84 | 85 | // Get the corner map from the computed Harris values 86 | cv::Mat getCornerMap(double qualityLevel) { 87 | 88 | cv::Mat cornerMap; 89 | 90 | // thresholding the corner strength 91 | threshold= qualityLevel*maxStrength; 92 | cv::threshold(cornerStrength,cornerTh,threshold,255,cv::THRESH_BINARY); 93 | 94 | // convert to 8-bit image 95 | cornerTh.convertTo(cornerMap,CV_8U); 96 | 97 | // non-maxima suppression 98 | cv::bitwise_and(cornerMap,localMax,cornerMap); 99 | 100 | return cornerMap; 101 | } 102 | 103 | // Get the feature points vector from the computed Harris values 104 | void getCorners(std::vector &points, double qualityLevel) { 105 | 106 | // Get the corner map 107 | cv::Mat cornerMap= getCornerMap(qualityLevel); 108 | // Get the corners 109 | getCorners(points, cornerMap); 110 | } 111 | 112 | // Get the feature points vector from the computed corner map 113 | void getCorners(std::vector &points, const cv::Mat& cornerMap) { 114 | 115 | // Iterate over the pixels to obtain all feature points 116 | for( int y = 0; y < cornerMap.rows; y++ ) { 117 | 118 | const uchar* rowPtr = cornerMap.ptr(y); 119 | 120 | for( int x = 0; x < cornerMap.cols; x++ ) { 121 | 122 | // if it is a feature point 123 | if (rowPtr[x]) { 124 | 125 | points.push_back(cv::Point(x,y)); 126 | } 127 | } 128 | } 129 | } 130 | 131 | // Draw circles at feature point locations on an image 132 | void drawOnImage(cv::Mat &image, const std::vector &points, cv::Scalar color= cv::Scalar(255,255,255), int radius=3, int thickness=1) { 133 | 134 | std::vector::const_iterator it= points.begin(); 135 | 136 | // for all corners 137 | while (it!=points.end()) { 138 | 139 | // draw a circle at each corner location 140 | cv::circle(image,*it,radius,color,thickness); 141 | ++it; 142 | } 143 | } 144 | }; 145 | 146 | #endif 147 | -------------------------------------------------------------------------------- /Chapter09/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # cmake for OpenCV2 Cookbook 2 | # your opencv/build directory should be in your system PATH 3 | 4 | # set minimum required version for cmake 5 | cmake_minimum_required(VERSION 2.8) 6 | 7 | # define the project name 8 | set(project_name "Chapter09") 9 | 10 | # set the project namee 11 | project("${project_name}") 12 | 13 | # add opencv package to the project 14 | find_package( OpenCV REQUIRED ) 15 | MESSAGE("OpenCV version : ${OpenCV_VERSION}") 16 | 17 | # add opencv include directories to the project 18 | include_directories( ${OpenCV_INCLUDE_DIRS} ) 19 | 20 | # add executable 21 | add_executable( patches patches.cpp) 22 | add_executable( matcher matcher.cpp) 23 | add_executable( binaryDescriptors binaryDescriptors.cpp) 24 | 25 | # link libraries 26 | target_link_libraries( patches ${OpenCV_LIBS}) 27 | target_link_libraries( matcher ${OpenCV_LIBS}) 28 | target_link_libraries( binaryDescriptors ${OpenCV_LIBS}) 29 | 30 | -------------------------------------------------------------------------------- /Chapter09/README.txt: -------------------------------------------------------------------------------- 1 | This directory contains material supporting chapter 9 of the cookbook: 2 | Computer Vision Programming using the OpenCV Library. 3 | Second Edition 4 | 5 | 6 | by Robert Laganiere, Packt Publishing, 2013. 7 | 8 | File: 9 | patches.cpp 10 | correspond to Recipe: 11 | Matching local templates 12 | 13 | File: 14 | matcher.cpp 15 | correspond to Recipe: 16 | Describing local intensity patterns 17 | 18 | File: 19 | binaryDescriptors.cpp 20 | correspond to Recipe: 21 | Describing keypoints with binary features 22 | 23 | You need the images: 24 | church01.jpg 25 | church02.jpg 26 | church03.jpg 27 | -------------------------------------------------------------------------------- /Chapter09/binaryDescriptors.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 9 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | int main() 29 | { 30 | // image matching 31 | 32 | // 1. Read input images 33 | cv::Mat image1= cv::imread("church01.jpg",CV_LOAD_IMAGE_GRAYSCALE); 34 | cv::Mat image2= cv::imread("church02.jpg",CV_LOAD_IMAGE_GRAYSCALE); 35 | 36 | // 2. Define keypoints vector 37 | std::vector keypoints1; 38 | std::vector keypoints2; 39 | 40 | // 3. Define feature detector 41 | // Construct the ORB feature detector object 42 | cv::Ptr detector = 43 | // new cv::BRISK(40); // to detect BRISK points 44 | new cv::ORB(100); // detect approx 100 ORB points 45 | 46 | // 4. Keypoint detection 47 | // Detect the ORB features 48 | detector->detect(image1,keypoints1); 49 | detector->detect(image2,keypoints2); 50 | 51 | // Draw feature points 52 | cv::Mat featureImage; 53 | cv::drawKeypoints(image1,keypoints1,featureImage,cv::Scalar(255,255,255),cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); 54 | 55 | // Display the corners 56 | cv::namedWindow("ORB"); 57 | cv::imshow("ORB",featureImage); 58 | 59 | std::cout << "Number of ORB keypoints (image 1): " << keypoints1.size() << std::endl; 60 | std::cout << "Number of ORB keypoints (image 2): " << keypoints2.size() << std::endl; 61 | 62 | // ORB includes both the detector and descriptor extractor 63 | cv::Ptr descriptor = detector; 64 | // new cv::FREAK(); // to describe with FREAK 65 | 66 | // 5. Extract the descriptor 67 | cv::Mat descriptors1; 68 | cv::Mat descriptors2; 69 | descriptor->compute(image1,keypoints1,descriptors1); 70 | descriptor->compute(image2,keypoints2,descriptors2); 71 | 72 | // Construction of the matcher 73 | cv::BFMatcher matcher( 74 | cv::NORM_HAMMING); // always use hamming norm 75 | // for binary descriptors 76 | // Match the two image descriptors 77 | std::vector matches; 78 | matcher.match(descriptors1,descriptors2, matches); 79 | 80 | // draw matches 81 | cv::Mat imageMatches; 82 | cv::drawMatches( 83 | image1,keypoints1, // 1st image and its keypoints 84 | image2,keypoints2, // 2nd image and its keypoints 85 | matches, // the matches 86 | imageMatches, // the image produced 87 | cv::Scalar(255,255,255), // color of lines 88 | cv::Scalar(255,255,255)); // color of points 89 | 90 | // Display the image of matches 91 | cv::namedWindow("ORB Matches"); 92 | cv::imshow("ORB Matches", imageMatches); 93 | // cv::namedWindow("FREAK Matches"); 94 | // cv::imshow("FREAK Matches", imageMatches); 95 | 96 | std::cout << "Number of matches: " << matches.size() << std::endl; 97 | 98 | cv::waitKey(); 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /Chapter09/patches.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 9 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | int main() 29 | { 30 | // image matching 31 | 32 | // 1. Read input images 33 | cv::Mat image1= cv::imread("church01.jpg",CV_LOAD_IMAGE_GRAYSCALE); 34 | cv::Mat image2= cv::imread("church02.jpg",CV_LOAD_IMAGE_GRAYSCALE); 35 | 36 | // 2. Define keypoints vector 37 | std::vector keypoints1; 38 | std::vector keypoints2; 39 | 40 | // 3. Define feature detector 41 | cv::FastFeatureDetector fastDet(80); 42 | 43 | // 4. Keypoint detection 44 | fastDet.detect(image1,keypoints1); 45 | fastDet.detect(image2,keypoints2); 46 | 47 | std::cout << "Number of keypoints (image 1): " << keypoints1.size() << std::endl; 48 | std::cout << "Number of keypoints (image 2): " << keypoints2.size() << std::endl; 49 | 50 | // 5. Define a square neighborhood 51 | const int nsize(11); // size of the neighborhood 52 | cv::Rect neighborhood(0, 0, nsize, nsize); // 11x11 53 | cv::Mat patch1; 54 | cv::Mat patch2; 55 | 56 | // 6. For all keypoints in first image 57 | // find best match in second image 58 | cv::Mat result; 59 | std::vector matches; 60 | 61 | //for all keypoints in image 1 62 | for (int i=0; i= image1.cols || neighborhood.y+nsize >= image1.rows) 71 | continue; 72 | 73 | //patch in image 1 74 | patch1 = image1(neighborhood); 75 | 76 | // reset best correlation value; 77 | cv::DMatch bestMatch; 78 | 79 | //for all keypoints in image 2 80 | for (int j=0; j= image2.cols || neighborhood.y + nsize >= image2.rows) 89 | continue; 90 | 91 | // patch in image 2 92 | patch2 = image2(neighborhood); 93 | 94 | // match the two patches 95 | cv::matchTemplate(patch1,patch2,result,CV_TM_SQDIFF_NORMED); 96 | 97 | // check if it is a best match 98 | if (result.at(0,0) < bestMatch.distance) { 99 | 100 | bestMatch.distance= result.at(0,0); 101 | bestMatch.queryIdx= i; 102 | bestMatch.trainIdx= j; 103 | } 104 | } 105 | 106 | // add the best match 107 | matches.push_back(bestMatch); 108 | } 109 | 110 | std::cout << "Number of matches: " << matches.size() << std::endl; 111 | 112 | // extract the 50 best matches 113 | std::nth_element(matches.begin(),matches.begin()+50,matches.end()); 114 | matches.erase(matches.begin()+50,matches.end()); 115 | 116 | std::cout << "Number of matches (after): " << matches.size() << std::endl; 117 | 118 | // Draw the matching results 119 | cv::Mat matchImage; 120 | cv::drawMatches(image1,keypoints1, // first image 121 | image2,keypoints2, // second image 122 | matches, // vector of matches 123 | matchImage, // produced image 124 | cv::Scalar(255,255,255), // line color 125 | cv::Scalar(255,255,255)); // point color 126 | 127 | // Display the image of matches 128 | cv::namedWindow("Matches"); 129 | cv::imshow("Matches",matchImage); 130 | 131 | // Match template 132 | 133 | // define a template 134 | cv::Mat target(image1,cv::Rect(80,105,30,30)); 135 | // Display the template 136 | cv::namedWindow("Template"); 137 | cv::imshow("Template",target); 138 | 139 | // define search region 140 | cv::Mat roi(image2, 141 | // here top half of the image 142 | cv::Rect(0,0,image2.cols,image2.rows/2)); 143 | 144 | // perform template matching 145 | cv::matchTemplate( 146 | roi, // search region 147 | target, // template 148 | result, // result 149 | CV_TM_SQDIFF); // similarity measure 150 | 151 | // find most similar location 152 | double minVal, maxVal; 153 | cv::Point minPt, maxPt; 154 | cv::minMaxLoc(result, &minVal, &maxVal, &minPt, &maxPt); 155 | 156 | // draw rectangle at most similar location 157 | // at minPt in this case 158 | cv::rectangle(roi, cv::Rect(minPt.x, minPt.y, target.cols , target.rows), 255); 159 | 160 | // Display the template 161 | cv::namedWindow("Best"); 162 | cv::imshow("Best",image2); 163 | 164 | cv::waitKey(); 165 | return 0; 166 | } -------------------------------------------------------------------------------- /Chapter10/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # cmake for OpenCV2 Cookbook 2 | # your opencv/build directory should be in your system PATH 3 | 4 | # set minimum required version for cmake 5 | cmake_minimum_required(VERSION 2.8) 6 | 7 | # define the project name 8 | set(project_name "Chapter10") 9 | 10 | # set the project namee 11 | project("${project_name}") 12 | 13 | # add opencv package to the project 14 | find_package( OpenCV REQUIRED ) 15 | MESSAGE("OpenCV version : ${OpenCV_VERSION}") 16 | 17 | # add opencv include directories to the project 18 | include_directories( ${OpenCV_INCLUDE_DIRS} ) 19 | # add include directory 20 | include_directories (${Chapter10_SOURCE_DIR}) 21 | 22 | # add executable 23 | add_executable( calibrate CameraCalibrator.cpp calibrate.cpp) 24 | add_executable( estimateF estimateF.cpp) 25 | add_executable( robustmatching robustmatching.cpp) 26 | add_executable( estimateH estimateH.cpp) 27 | 28 | # link libraries 29 | target_link_libraries( calibrate ${OpenCV_LIBS}) 30 | target_link_libraries( estimateF ${OpenCV_LIBS}) 31 | target_link_libraries( robustmatching ${OpenCV_LIBS}) 32 | target_link_libraries( estimateH ${OpenCV_LIBS}) 33 | 34 | -------------------------------------------------------------------------------- /Chapter10/CameraCalibrator.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 10 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include "CameraCalibrator.h" 20 | 21 | // Open chessboard images and extract corner points 22 | int CameraCalibrator::addChessboardPoints( 23 | const std::vector& filelist, // list of filenames containing board images 24 | cv::Size & boardSize, // size of the board 25 | std::string windowName) { // name of window to display results 26 | // if null, no display shown 27 | // the points on the chessboard 28 | std::vector imageCorners; 29 | std::vector objectCorners; 30 | 31 | // 3D Scene Points: 32 | // Initialize the chessboard corners 33 | // in the chessboard reference frame 34 | // The corners are at 3D location (X,Y,Z)= (i,j,0) 35 | for (int i=0; i0) { 73 | 74 | //Draw the corners 75 | cv::drawChessboardCorners(image, boardSize, imageCorners, found); 76 | cv::imshow(windowName, image); 77 | cv::waitKey(100); 78 | } 79 | } 80 | 81 | return successes; 82 | } 83 | 84 | // Add scene points and corresponding image points 85 | void CameraCalibrator::addPoints(const std::vector& imageCorners, const std::vector& objectCorners) { 86 | 87 | // 2D image points from one view 88 | imagePoints.push_back(imageCorners); 89 | // corresponding 3D scene points 90 | objectPoints.push_back(objectCorners); 91 | } 92 | 93 | // Calibrate the camera 94 | // returns the re-projection error 95 | double CameraCalibrator::calibrate(const cv::Size imageSize) 96 | { 97 | // undistorter must be reinitialized 98 | mustInitUndistort= true; 99 | 100 | //Output rotations and translations 101 | std::vector rvecs, tvecs; 102 | 103 | // start calibration 104 | return 105 | calibrateCamera(objectPoints, // the 3D points 106 | imagePoints, // the image points 107 | imageSize, // image size 108 | cameraMatrix, // output camera matrix 109 | distCoeffs, // output distortion matrix 110 | rvecs, tvecs, // Rs, Ts 111 | flag); // set options 112 | // ,CV_CALIB_USE_INTRINSIC_GUESS); 113 | 114 | } 115 | 116 | // remove distortion in an image (after calibration) 117 | cv::Mat CameraCalibrator::remap(const cv::Mat &image) { 118 | 119 | cv::Mat undistorted; 120 | 121 | if (mustInitUndistort) { // called once per calibration 122 | 123 | cv::initUndistortRectifyMap( 124 | cameraMatrix, // computed camera matrix 125 | distCoeffs, // computed distortion matrix 126 | cv::Mat(), // optional rectification (none) 127 | cv::Mat(), // camera matrix to generate undistorted 128 | // cv::Size(640,480), 129 | image.size(), // size of undistorted 130 | CV_32FC1, // type of output map 131 | map1, map2); // the x and y mapping functions 132 | 133 | mustInitUndistort= false; 134 | } 135 | 136 | // Apply mapping functions 137 | cv::remap(image, undistorted, map1, map2, 138 | cv::INTER_LINEAR); // interpolation type 139 | 140 | return undistorted; 141 | } 142 | 143 | 144 | // Set the calibration options 145 | // 8radialCoeffEnabled should be true if 8 radial coefficients are required (5 is default) 146 | // tangentialParamEnabled should be true if tangeantial distortion is present 147 | void CameraCalibrator::setCalibrationFlag(bool radial8CoeffEnabled, bool tangentialParamEnabled) { 148 | 149 | // Set the flag used in cv::calibrateCamera() 150 | flag = 0; 151 | if (!tangentialParamEnabled) flag += CV_CALIB_ZERO_TANGENT_DIST; 152 | if (radial8CoeffEnabled) flag += CV_CALIB_RATIONAL_MODEL; 153 | } 154 | 155 | -------------------------------------------------------------------------------- /Chapter10/CameraCalibrator.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 10 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #ifndef CAMERACALIBRATOR_H 20 | #define CAMERACALIBRATOR_H 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | #include "opencv2/imgproc/imgproc.hpp" 27 | #include "opencv2/calib3d/calib3d.hpp" 28 | #include 29 | 30 | class CameraCalibrator { 31 | 32 | // input points: 33 | // the points in world coordinates 34 | std::vector > objectPoints; 35 | // the point positions in pixels 36 | std::vector > imagePoints; 37 | // output Matrices 38 | cv::Mat cameraMatrix; 39 | cv::Mat distCoeffs; 40 | // flag to specify how calibration is done 41 | int flag; 42 | // used in image undistortion 43 | cv::Mat map1,map2; 44 | bool mustInitUndistort; 45 | 46 | public: 47 | CameraCalibrator() : flag(0), mustInitUndistort(true) {} 48 | 49 | // Open the chessboard images and extract corner points 50 | int addChessboardPoints(const std::vector& filelist, cv::Size & boardSize, std::string windowName=""); 51 | // Add scene points and corresponding image points 52 | void addPoints(const std::vector& imageCorners, const std::vector& objectCorners); 53 | // Calibrate the camera 54 | double calibrate(const cv::Size imageSize); 55 | // Set the calibration flag 56 | void setCalibrationFlag(bool radial8CoeffEnabled=false, bool tangentialParamEnabled=false); 57 | // Remove distortion in an image (after calibration) 58 | cv::Mat remap(const cv::Mat &image); 59 | 60 | // Getters 61 | cv::Mat getCameraMatrix() { return cameraMatrix; } 62 | cv::Mat getDistCoeffs() { return distCoeffs; } 63 | }; 64 | 65 | #endif // CAMERACALIBRATOR_H 66 | -------------------------------------------------------------------------------- /Chapter10/README.txt: -------------------------------------------------------------------------------- 1 | This directory contains material supporting chapter 9 of the cookbook: 2 | Computer Vision Programming using the OpenCV Library. 3 | by Robert Laganiere, Packt Publishing, 2011. 4 | 5 | Files: 6 | CameraCalibrator.h 7 | CameraCalibrator.cpp 8 | calibrate.cpp 9 | correspond to Recipes: 10 | Calibrating a camera 11 | File: 12 | estimateF.cpp 13 | correspond to Recipe: 14 | Computing the Fundamental Matrix of an Image Pair 15 | Files: 16 | matcher.h 17 | robustmatching.cpp 18 | correspond to Recipe: 19 | Matching Images using Random Sample Consensus 20 | File: 21 | estimateH.cpp 22 | correspond to Recipe: 23 | Computing a homography between two images 24 | 25 | You need the images: 26 | 27 | chessboards/* 28 | church01.jpg 29 | church02.jpg 30 | church03.jpg 31 | parliament1.jpg 32 | parliament2.jpg 33 | 34 | 35 | -------------------------------------------------------------------------------- /Chapter10/calibrate.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 10 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "CameraCalibrator.h" 28 | 29 | // Applies a lookup table transforming an input image into a 1-channel image 30 | cv::Mat applyLookUp(const cv::Mat& image, const cv::MatND& lookup) { 31 | 32 | // Set output image (always 1-channel) 33 | cv::Mat result(image.rows,image.cols,CV_8U); 34 | cv::Mat_::iterator itr= result.begin(); 35 | 36 | // Iterates over the input image 37 | cv::Mat_::const_iterator it= image.begin(); 38 | cv::Mat_::const_iterator itend= image.end(); 39 | 40 | // Applies lookup to each pixel 41 | for ( ; it!= itend; ++it, ++itr) { 42 | 43 | *itr= lookup.at(*it); 44 | } 45 | return result; 46 | } 47 | 48 | int main() 49 | { 50 | cv::namedWindow("Board Image"); 51 | cv::Mat image; 52 | std::vector filelist; 53 | 54 | // generate list of chessboard image filename 55 | for (int i=1; i<=20; i++) { 56 | 57 | std::stringstream str; 58 | str << "chessboards/chessboard" << std::setw(2) << std::setfill('0') << i << ".jpg"; 59 | std::cout << str.str() << std::endl; 60 | 61 | filelist.push_back(str.str()); 62 | image= cv::imread(str.str(),0); 63 | cv::imshow("Board Image",image); 64 | 65 | cv::waitKey(100); 66 | } 67 | 68 | // Create calibrator object 69 | CameraCalibrator cameraCalibrator; 70 | // add the corners from the chessboard 71 | cv::Size boardSize(6,4); 72 | cameraCalibrator.addChessboardPoints( 73 | filelist, // filenames of chessboard image 74 | boardSize, "Detected points"); // size of chessboard 75 | 76 | // calibrate the camera 77 | // cameraCalibrator.setCalibrationFlag(true,true); 78 | cameraCalibrator.calibrate(image.size()); 79 | 80 | // Image Undistortion 81 | image = cv::imread(filelist[6],0); 82 | cv::Mat uImage= cameraCalibrator.remap(image); 83 | 84 | // display camera matrix 85 | cv::Mat cameraMatrix= cameraCalibrator.getCameraMatrix(); 86 | std::cout << " Camera intrinsic: " << cameraMatrix.rows << "x" << cameraMatrix.cols << std::endl; 87 | std::cout << cameraMatrix.at(0,0) << " " << cameraMatrix.at(0,1) << " " << cameraMatrix.at(0,2) << std::endl; 88 | std::cout << cameraMatrix.at(1,0) << " " << cameraMatrix.at(1,1) << " " << cameraMatrix.at(1,2) << std::endl; 89 | std::cout << cameraMatrix.at(2,0) << " " << cameraMatrix.at(2,1) << " " << cameraMatrix.at(2,2) << std::endl; 90 | 91 | cv::namedWindow("Original Image"); 92 | cv::imshow("Original Image", image); 93 | cv::namedWindow("Undistorted Image"); 94 | cv::imshow("Undistorted Image", uImage); 95 | 96 | cv::waitKey(); 97 | return 0; 98 | 99 | // Create an image inversion table 100 | int dim(256); 101 | cv::Mat lut(1, // 1 dimension 102 | &dim, // 256 entries 103 | CV_8U); // uchar 104 | 105 | for (int i=0; i<256; i++) { 106 | 107 | lut.at(i)= 255-i; 108 | } 109 | 110 | // Apply lookup and display negative image 111 | cv::namedWindow("Negative image"); 112 | // cv::imshow("Negative image",h.applyLookUp(image,lookup)); 113 | cv::imshow("Negative image",applyLookUp(image,lut)); 114 | 115 | 116 | cv::waitKey(); 117 | return 0; 118 | } 119 | -------------------------------------------------------------------------------- /Chapter10/estimateH.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 10 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | int main() 29 | { 30 | // Read input images 31 | cv::Mat image1= cv::imread("parliament1.bmp",0); 32 | cv::Mat image2= cv::imread("parliament2.bmp",0); 33 | if (!image1.data || !image2.data) 34 | return 0; 35 | 36 | // Display the images 37 | cv::namedWindow("Image 1"); 38 | cv::imshow("Image 1",image1); 39 | cv::namedWindow("Image 2"); 40 | cv::imshow("Image 2",image2); 41 | 42 | // 0. Construction of the detector and descriptor 43 | // for example SURF 44 | cv::Ptr detector= new cv::SURF(); 45 | cv::Ptr extractor= detector; 46 | 47 | // 1. Detection of the feature points 48 | std::vector keypoints1; 49 | std::vector keypoints2; 50 | detector->detect(image1,keypoints1); 51 | detector->detect(image2,keypoints2); 52 | 53 | std::cout << "Number of feature points (1): " << keypoints1.size() << std::endl; 54 | std::cout << "Number of feature points (2): " << keypoints2.size() << std::endl; 55 | 56 | // 2. Extraction of the feature descriptors 57 | cv::Mat descriptors1, descriptors2; 58 | extractor->compute(image1,keypoints1,descriptors1); 59 | extractor->compute(image2,keypoints2,descriptors2); 60 | 61 | // 3. Match the two image descriptors 62 | 63 | // Construction of the matcher with crosscheck 64 | cv::BFMatcher matcher(cv::NORM_L2, true); 65 | // matching 66 | std::vector matches; 67 | matcher.match(descriptors1,descriptors2,matches); 68 | 69 | // draw the matches 70 | cv::Mat imageMatches; 71 | cv::drawMatches(image1,keypoints1, // 1st image and its keypoints 72 | image2,keypoints2, // 2nd image and its keypoints 73 | matches, // the matches 74 | imageMatches, // the image produced 75 | cv::Scalar(255,255,255), // color of the lines 76 | cv::Scalar(255,255,255), // color of the keypoints 77 | std::vector(), 78 | 2); 79 | cv::namedWindow("Matches"); 80 | cv::imshow("Matches",imageMatches); 81 | 82 | // Convert keypoints into Point2f 83 | std::vector points1, points2; 84 | for (std::vector::const_iterator it= matches.begin(); 85 | it!= matches.end(); ++it) { 86 | 87 | // Get the position of left keypoints 88 | float x= keypoints1[it->queryIdx].pt.x; 89 | float y= keypoints1[it->queryIdx].pt.y; 90 | points1.push_back(cv::Point2f(x,y)); 91 | // Get the position of right keypoints 92 | x= keypoints2[it->trainIdx].pt.x; 93 | y= keypoints2[it->trainIdx].pt.y; 94 | points2.push_back(cv::Point2f(x,y)); 95 | } 96 | 97 | std::cout << points1.size() << " " << points2.size() << std::endl; 98 | 99 | // Find the homography between image 1 and image 2 100 | std::vector inliers(points1.size(),0); 101 | cv::Mat homography= cv::findHomography( 102 | points1,points2, // corresponding points 103 | inliers, // outputed inliers matches 104 | CV_RANSAC, // RANSAC method 105 | 1.); // max distance to reprojection point 106 | 107 | // Draw the inlier points 108 | std::vector::const_iterator itPts= points1.begin(); 109 | std::vector::const_iterator itIn= inliers.begin(); 110 | while (itPts!=points1.end()) { 111 | 112 | // draw a circle at each inlier location 113 | if (*itIn) 114 | cv::circle(image1,*itPts,3,cv::Scalar(255,255,255)); 115 | 116 | ++itPts; 117 | ++itIn; 118 | } 119 | 120 | itPts= points2.begin(); 121 | itIn= inliers.begin(); 122 | while (itPts!=points2.end()) { 123 | 124 | // draw a circle at each inlier location 125 | if (*itIn) 126 | cv::circle(image2,*itPts,3,cv::Scalar(255,255,255)); 127 | 128 | ++itPts; 129 | ++itIn; 130 | } 131 | 132 | // Display the images with points 133 | cv::namedWindow("Image 1 Homography Points"); 134 | cv::imshow("Image 1 Homography Points",image1); 135 | cv::namedWindow("Image 2 Homography Points"); 136 | cv::imshow("Image 2 Homography Points",image2); 137 | 138 | // Warp image 1 to image 2 139 | cv::Mat result; 140 | cv::warpPerspective(image1, // input image 141 | result, // output image 142 | homography, // homography 143 | cv::Size(2*image1.cols,image1.rows)); // size of output image 144 | 145 | // Copy image 1 on the first half of full image 146 | cv::Mat half(result,cv::Rect(0,0,image2.cols,image2.rows)); 147 | image2.copyTo(half); 148 | 149 | // Display the warp image 150 | cv::namedWindow("Image mosaic"); 151 | cv::imshow("Image mosaic",result); 152 | 153 | cv::waitKey(); 154 | return 0; 155 | } -------------------------------------------------------------------------------- /Chapter10/matchingTarget.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 10 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "targetMatcher.h" 28 | 29 | int main() 30 | { 31 | // Read input images 32 | cv::Mat target= cv::imread("cookbook1.bmp",0); 33 | cv::Mat image= cv::imread("book.jpg",0); 34 | if (!target.data || !image.data) 35 | return 0; 36 | 37 | // Display the images 38 | cv::namedWindow("Target"); 39 | cv::imshow("Target",target); 40 | 41 | // Prepare the matcher 42 | TargetMatcher tmatcher("FAST","FREAK"); 43 | tmatcher.setNormType(cv::NORM_HAMMING); 44 | 45 | // definition of the output data 46 | std::vector matches; 47 | std::vector keypoints1, keypoints2; 48 | std::vector corners; 49 | // the reference image 50 | tmatcher.setTarget(target); 51 | // match image with target 52 | tmatcher.detectTarget(image,corners,matches,keypoints1,keypoints2); 53 | // draw the target corners on the image 54 | cv::Point pt= cv::Point(corners[0]); 55 | cv::line(image,cv::Point(corners[0]),cv::Point(corners[1]),cv::Scalar(255,255,255),3); 56 | cv::line(image,cv::Point(corners[1]),cv::Point(corners[2]),cv::Scalar(255,255,255),3); 57 | cv::line(image,cv::Point(corners[2]),cv::Point(corners[3]),cv::Scalar(255,255,255),3); 58 | cv::line(image,cv::Point(corners[3]),cv::Point(corners[0]),cv::Scalar(255,255,255),3); 59 | 60 | cv::namedWindow("Image"); 61 | cv::imshow("Image",image); 62 | 63 | // draw the matches 64 | cv::Mat imageMatches; 65 | cv::drawMatches(target,keypoints1, // 1st image and its keypoints 66 | image,keypoints2, // 2nd image and its keypoints 67 | matches, // the matches 68 | imageMatches, // the image produced 69 | cv::Scalar(255,255,255), // color of the lines 70 | cv::Scalar(255,255,255), // color of the keypoints 71 | std::vector(), 72 | 2); 73 | cv::namedWindow("Matches"); 74 | cv::imshow("Matches",imageMatches); 75 | 76 | 77 | /* 78 | // Convert keypoints into Point2f 79 | std::vector points1, points2; 80 | 81 | for (std::vector::const_iterator it= matches.begin(); 82 | it!= matches.end(); ++it) { 83 | 84 | // Get the position of left keypoints 85 | float x= keypoints1[it->queryIdx].pt.x; 86 | float y= keypoints1[it->queryIdx].pt.y; 87 | points1.push_back(cv::Point2f(x,y)); 88 | cv::circle(image1,cv::Point(x,y),3,cv::Scalar(255,255,255),3); 89 | // Get the position of right keypoints 90 | x= keypoints2[it->trainIdx].pt.x; 91 | y= keypoints2[it->trainIdx].pt.y; 92 | cv::circle(image2,cv::Point(x,y),3,cv::Scalar(255,255,255),3); 93 | points2.push_back(cv::Point2f(x,y)); 94 | } 95 | 96 | // Draw the epipolar lines 97 | std::vector lines1; 98 | cv::computeCorrespondEpilines(cv::Mat(points1),1,fundemental,lines1); 99 | 100 | for (std::vector::const_iterator it= lines1.begin(); 101 | it!=lines1.end(); ++it) { 102 | 103 | cv::line(image2,cv::Point(0,-(*it)[2]/(*it)[1]), 104 | cv::Point(image2.cols,-((*it)[2]+(*it)[0]*image2.cols)/(*it)[1]), 105 | cv::Scalar(255,255,255)); 106 | } 107 | 108 | std::vector lines2; 109 | cv::computeCorrespondEpilines(cv::Mat(points2),2,fundemental,lines2); 110 | 111 | for (std::vector::const_iterator it= lines2.begin(); 112 | it!=lines2.end(); ++it) { 113 | 114 | cv::line(image1,cv::Point(0,-(*it)[2]/(*it)[1]), 115 | cv::Point(image1.cols,-((*it)[2]+(*it)[0]*image1.cols)/(*it)[1]), 116 | cv::Scalar(255,255,255)); 117 | } 118 | 119 | // Display the images with epipolar lines 120 | cv::namedWindow("Right Image Epilines (RANSAC)"); 121 | cv::imshow("Right Image Epilines (RANSAC)",image1); 122 | cv::namedWindow("Left Image Epilines (RANSAC)"); 123 | cv::imshow("Left Image Epilines (RANSAC)",image2); 124 | */ 125 | cv::waitKey(); 126 | return 0; 127 | } -------------------------------------------------------------------------------- /Chapter10/robustmatching.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 10 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "robustMatcher.h" 28 | 29 | int main() 30 | { 31 | // to be able to construct SURF and SIFT 32 | cv::initModule_nonfree(); 33 | 34 | // Read input images 35 | cv::Mat image1= cv::imread("church01.jpg",0); 36 | cv::Mat image2= cv::imread("church03.jpg",0); 37 | if (!image1.data || !image2.data) 38 | return 0; 39 | 40 | // Display the images 41 | cv::namedWindow("Right Image"); 42 | cv::imshow("Right Image",image1); 43 | cv::namedWindow("Left Image"); 44 | cv::imshow("Left Image",image2); 45 | 46 | // Prepare the matcher (with default parameters) 47 | RobustMatcher rmatcher("SURF"); 48 | 49 | // Match the two images 50 | std::vector matches; 51 | 52 | std::vector keypoints1, keypoints2; 53 | cv::Mat fundamental= rmatcher.match(image1,image2,matches, 54 | keypoints1, keypoints2); 55 | 56 | // draw the matches 57 | cv::Mat imageMatches; 58 | cv::drawMatches(image1,keypoints1, // 1st image and its keypoints 59 | image2,keypoints2, // 2nd image and its keypoints 60 | matches, // the matches 61 | imageMatches, // the image produced 62 | cv::Scalar(255,255,255), // color of the lines 63 | cv::Scalar(255,255,255), // color of the keypoints 64 | std::vector(), 65 | 2); 66 | cv::namedWindow("Matches"); 67 | cv::imshow("Matches",imageMatches); 68 | 69 | // Convert keypoints into Point2f 70 | std::vector points1, points2; 71 | 72 | for (std::vector::const_iterator it= matches.begin(); 73 | it!= matches.end(); ++it) { 74 | 75 | // Get the position of left keypoints 76 | float x= keypoints1[it->queryIdx].pt.x; 77 | float y= keypoints1[it->queryIdx].pt.y; 78 | points1.push_back(keypoints1[it->queryIdx].pt); 79 | cv::circle(image1,cv::Point(x,y),3,cv::Scalar(255,255,255),3); 80 | // Get the position of right keypoints 81 | x= keypoints2[it->trainIdx].pt.x; 82 | y= keypoints2[it->trainIdx].pt.y; 83 | cv::circle(image2,cv::Point(x,y),3,cv::Scalar(255,255,255),3); 84 | points2.push_back(keypoints2[it->trainIdx].pt); 85 | } 86 | 87 | // Draw the epipolar lines 88 | std::vector lines1; 89 | cv::computeCorrespondEpilines(points1,1,fundamental,lines1); 90 | 91 | for (std::vector::const_iterator it= lines1.begin(); 92 | it!=lines1.end(); ++it) { 93 | 94 | cv::line(image2,cv::Point(0,-(*it)[2]/(*it)[1]), 95 | cv::Point(image2.cols,-((*it)[2]+(*it)[0]*image2.cols)/(*it)[1]), 96 | cv::Scalar(255,255,255)); 97 | } 98 | 99 | std::vector lines2; 100 | cv::computeCorrespondEpilines(points2,2,fundamental,lines2); 101 | 102 | for (std::vector::const_iterator it= lines2.begin(); 103 | it!=lines2.end(); ++it) { 104 | 105 | cv::line(image1,cv::Point(0,-(*it)[2]/(*it)[1]), 106 | cv::Point(image1.cols,-((*it)[2]+(*it)[0]*image1.cols)/(*it)[1]), 107 | cv::Scalar(255,255,255)); 108 | } 109 | 110 | // Display the images with epipolar lines 111 | cv::namedWindow("Right Image Epilines (RANSAC)"); 112 | cv::imshow("Right Image Epilines (RANSAC)",image1); 113 | cv::namedWindow("Left Image Epilines (RANSAC)"); 114 | cv::imshow("Left Image Epilines (RANSAC)",image2); 115 | 116 | cv::waitKey(); 117 | return 0; 118 | } -------------------------------------------------------------------------------- /Chapter11/BGFGSegmentor.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 11 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #if !defined BGFGSeg 20 | #define BGFGSeg 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "videoprocessor.h" 27 | 28 | class BGFGSegmentor : public FrameProcessor { 29 | 30 | cv::Mat gray; // current gray-level image 31 | cv::Mat background; // accumulated background 32 | cv::Mat backImage; // current background image 33 | cv::Mat foreground; // foreground image 34 | double learningRate; // learning rate in background accumulation 35 | int threshold; // threshold for foreground extraction 36 | 37 | public: 38 | 39 | BGFGSegmentor() : threshold(10), learningRate(0.01) {} 40 | 41 | // Set the threshold used to declare a foreground 42 | void setThreshold(int t) { 43 | 44 | threshold= t; 45 | } 46 | 47 | // Set the learning rate 48 | void setLearningRate(double r) { 49 | 50 | learningRate= r; 51 | } 52 | 53 | // processing method 54 | void process(cv:: Mat &frame, cv:: Mat &output) { 55 | 56 | // convert to gray-level image 57 | cv::cvtColor(frame, gray, CV_BGR2GRAY); 58 | 59 | // initialize background to 1st frame 60 | if (background.empty()) 61 | gray.convertTo(background, CV_32F); 62 | 63 | // convert background to 8U 64 | background.convertTo(backImage,CV_8U); 65 | 66 | // compute difference between current image and background 67 | cv::absdiff(backImage,gray,foreground); 68 | 69 | // apply threshold to foreground image 70 | cv::threshold(foreground,output,threshold,255,cv::THRESH_BINARY_INV); 71 | 72 | // accumulate background 73 | cv::accumulateWeighted(gray, background, 74 | // alpha*gray + (1-alpha)*background 75 | learningRate, // alpha 76 | output); // mask 77 | } 78 | }; 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /Chapter11/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # cmake for OpenCV2 Cookbook 2 | # your opencv/build directory should be in your system PATH 3 | 4 | # set minimum required version for cmake 5 | cmake_minimum_required(VERSION 2.8) 6 | 7 | # define the project name 8 | set(project_name "Chapter11") 9 | 10 | # set the project namee 11 | project("${project_name}") 12 | 13 | # add opencv package to the project 14 | find_package( OpenCV REQUIRED ) 15 | MESSAGE("OpenCV version : ${OpenCV_VERSION}") 16 | 17 | # add opencv include directories to the project 18 | include_directories( ${OpenCV_INCLUDE_DIRS} ) 19 | # add include directory 20 | include_directories (${Chapter11_SOURCE_DIR}) 21 | 22 | # add executable 23 | add_executable( videoprocessing videoprocessing.cpp) 24 | add_executable( tracking tracking.cpp) 25 | add_executable( foreground foreground.cpp) 26 | 27 | # link libraries 28 | target_link_libraries( videoprocessing ${OpenCV_LIBS}) 29 | target_link_libraries( tracking ${OpenCV_LIBS}) 30 | target_link_libraries( foreground ${OpenCV_LIBS}) 31 | 32 | -------------------------------------------------------------------------------- /Chapter11/README.txt: -------------------------------------------------------------------------------- 1 | This directory contains material supporting chapter 10 of the cookbook: 2 | Computer Vision Programming using the OpenCV Library. 3 | by Robert Laganiere, Packt Publishing, 2011. 4 | 5 | Files: 6 | videoprocessing.cpp 7 | videoprocessor.h 8 | correspond to Recipes: 9 | Reading Video Sequences 10 | Processing the Video Frames 11 | Writing Video Sequences 12 | 13 | Files: 14 | featuretracker.h 15 | tracking.cpp 16 | correspond to Recipe: 17 | Tracking Feature Points in Video 18 | 19 | Files: 20 | BGFGSegmentor.h 21 | foreground.cpp 22 | correspond to Recipe: 23 | Extracting the Foreground Objects in Video 24 | 25 | You need the image sequence: 26 | bike.avi -------------------------------------------------------------------------------- /Chapter11/featuretracker.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 11 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #if !defined FTRACKER 20 | #define FTRACKER 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "videoprocessor.h" 31 | 32 | class FeatureTracker : public FrameProcessor { 33 | 34 | cv::Mat gray; // current gray-level image 35 | cv::Mat gray_prev; // previous gray-level image 36 | std::vector points[2]; // tracked features from 0->1 37 | std::vector initial; // initial position of tracked points 38 | std::vector features; // detected features 39 | int max_count; // maximum number of features to detect 40 | double qlevel; // quality level for feature detection 41 | double minDist; // minimum distance between two feature points 42 | std::vector status; // status of tracked features 43 | std::vector err; // error in tracking 44 | 45 | public: 46 | 47 | FeatureTracker() : max_count(500), qlevel(0.01), minDist(10.) {} 48 | 49 | // processing method 50 | void process(cv:: Mat &frame, cv:: Mat &output) { 51 | 52 | // convert to gray-level image 53 | cv::cvtColor(frame, gray, CV_BGR2GRAY); 54 | frame.copyTo(output); 55 | 56 | // 1. if new feature points must be added 57 | if(addNewPoints()) 58 | { 59 | // detect feature points 60 | detectFeaturePoints(); 61 | // add the detected features to the currently tracked features 62 | points[0].insert(points[0].end(),features.begin(),features.end()); 63 | initial.insert(initial.end(),features.begin(),features.end()); 64 | } 65 | 66 | // for first image of the sequence 67 | if(gray_prev.empty()) 68 | gray.copyTo(gray_prev); 69 | 70 | // 2. track features 71 | cv::calcOpticalFlowPyrLK(gray_prev, gray, // 2 consecutive images 72 | points[0], // input point position in first image 73 | points[1], // output point postion in the second image 74 | status, // tracking success 75 | err); // tracking error 76 | 77 | // 3. loop over the tracked points to reject the undesirables 78 | int k=0; 79 | for( int i= 0; i < points[1].size(); i++ ) { 80 | 81 | // do we keep this point? 82 | if (acceptTrackedPoint(i)) { 83 | 84 | // keep this point in vector 85 | initial[k]= initial[i]; 86 | points[1][k++] = points[1][i]; 87 | } 88 | } 89 | 90 | // eliminate unsuccesful points 91 | points[1].resize(k); 92 | initial.resize(k); 93 | 94 | // 4. handle the accepted tracked points 95 | handleTrackedPoints(frame, output); 96 | 97 | // 5. current points and image become previous ones 98 | std::swap(points[1], points[0]); 99 | cv::swap(gray_prev, gray); 100 | } 101 | 102 | // feature point detection 103 | void detectFeaturePoints() { 104 | 105 | // detect the features 106 | cv::goodFeaturesToTrack(gray, // the image 107 | features, // the output detected features 108 | max_count, // the maximum number of features 109 | qlevel, // quality level 110 | minDist); // min distance between two features 111 | } 112 | 113 | // determine if new points should be added 114 | bool addNewPoints() { 115 | 116 | // if too few points 117 | return points[0].size()<=10; 118 | } 119 | 120 | // determine which tracked point should be accepted 121 | // here we keep only moving points 122 | bool acceptTrackedPoint(int i) { 123 | 124 | return status[i] && 125 | // if point has moved 126 | (abs(points[0][i].x-points[1][i].x)+ 127 | (abs(points[0][i].y-points[1][i].y))>2); 128 | } 129 | 130 | // handle the currently tracked points 131 | void handleTrackedPoints(cv:: Mat &frame, cv:: Mat &output) { 132 | 133 | // for all tracked points 134 | for(int i= 0; i < points[1].size(); i++ ) { 135 | 136 | // draw line and circle 137 | cv::line(output, initial[i], points[1][i], cv::Scalar(255,255,255)); 138 | cv::circle(output, points[1][i], 3, cv::Scalar(255,255,255),-1); 139 | } 140 | } 141 | }; 142 | 143 | #endif 144 | -------------------------------------------------------------------------------- /Chapter11/foreground.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 11 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "videoprocessor.h" 26 | #include "BGFGSegmentor.h" 27 | 28 | int main() 29 | { 30 | // Open the video file 31 | cv::VideoCapture capture("bike.avi"); 32 | // check if video successfully opened 33 | if (!capture.isOpened()) 34 | return 0; 35 | 36 | // current video frame 37 | cv::Mat frame; 38 | // foreground binary image 39 | cv::Mat foreground; 40 | // background image 41 | cv::Mat background; 42 | 43 | cv::namedWindow("Extracted Foreground"); 44 | 45 | // The Mixture of Gaussian object 46 | // used with all default parameters 47 | cv::BackgroundSubtractorMOG mog; 48 | 49 | bool stop(false); 50 | // for all frames in video 51 | while (!stop) { 52 | 53 | // read next frame if any 54 | if (!capture.read(frame)) 55 | break; 56 | 57 | // update the background 58 | // and return the foreground 59 | mog(frame,foreground,0.01); 60 | 61 | // Complement the image 62 | cv::threshold(foreground,foreground,128,255,cv::THRESH_BINARY_INV); 63 | 64 | // show foreground and background 65 | cv::imshow("Extracted Foreground",foreground); 66 | 67 | // introduce a delay 68 | // or press key to stop 69 | if (cv::waitKey(10)>=0) 70 | stop= true; 71 | } 72 | 73 | cv::waitKey(); 74 | 75 | // Create video procesor instance 76 | VideoProcessor processor; 77 | 78 | // Create background/foreground segmentor 79 | BGFGSegmentor segmentor; 80 | segmentor.setThreshold(25); 81 | 82 | // Open video file 83 | processor.setInput("bike.avi"); 84 | 85 | // set frame processor 86 | processor.setFrameProcessor(&segmentor); 87 | 88 | // Declare a window to display the video 89 | processor.displayOutput("Extracted Foreground"); 90 | 91 | // Play the video at the original frame rate 92 | processor.setDelay(1000./processor.getFrameRate()); 93 | 94 | // Start the process 95 | processor.run(); 96 | 97 | cv::waitKey(); 98 | } -------------------------------------------------------------------------------- /Chapter11/tracking.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 10 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "featuretracker.h" 27 | 28 | int main() 29 | { 30 | // Create video procesor instance 31 | VideoProcessor processor; 32 | 33 | // Create feature tracker instance 34 | FeatureTracker tracker; 35 | 36 | // Open video file 37 | processor.setInput("bike.avi"); 38 | 39 | // set frame processor 40 | processor.setFrameProcessor(&tracker); 41 | 42 | // Declare a window to display the video 43 | processor.displayOutput("Tracked Features"); 44 | 45 | // Play the video at the original frame rate 46 | processor.setDelay(1000./processor.getFrameRate()); 47 | 48 | processor.stopAtFrameNo(90); 49 | 50 | // Start the process 51 | processor.run(); 52 | 53 | cv::waitKey(); 54 | } -------------------------------------------------------------------------------- /Chapter11/videoprocessing.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------------------------*\ 2 | This file contains material supporting chapter 11 of the cookbook: 3 | Computer Vision Programming using the OpenCV Library 4 | Second Edition 5 | by Robert Laganiere, Packt Publishing, 2013. 6 | 7 | This program is free software; permission is hereby granted to use, copy, modify, 8 | and distribute this source code, or portions thereof, for any purpose, without fee, 9 | subject to the restriction that the copyright notice may not be removed 10 | or altered from any source or altered source distribution. 11 | The software is released on an as-is basis and without any warranties of any kind. 12 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 13 | The author disclaims all warranties with regard to this software, any use, 14 | and any consequent failure, is purely the responsibility of the user. 15 | 16 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 17 | \*------------------------------------------------------------------------------------------*/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "videoprocessor.h" 27 | 28 | void draw(const cv::Mat& img, cv::Mat& out) { 29 | 30 | img.copyTo(out); 31 | cv::circle(out, cv::Point(100,100),5,cv::Scalar(255,0,0),2); 32 | } 33 | 34 | // processing function 35 | void canny(cv::Mat& img, cv::Mat& out) { 36 | 37 | // Convert to gray 38 | if (img.channels()==3) 39 | cv::cvtColor(img,out,CV_BGR2GRAY); 40 | // Compute Canny edges 41 | cv::Canny(out,out,100,200); 42 | // Invert the image 43 | cv::threshold(out,out,128,255,cv::THRESH_BINARY_INV); 44 | } 45 | 46 | int main() 47 | { 48 | // Open the video file 49 | cv::VideoCapture capture("bike.avi"); 50 | // cv::VideoCapture capture("http://www.laganiere.name/bike.avi"); 51 | // check if video successfully opened 52 | if (!capture.isOpened()) 53 | return 1; 54 | 55 | // Get the frame rate 56 | double rate= capture.get(CV_CAP_PROP_FPS); 57 | std::cout << "Frame rate: " << rate << "fps" << std::endl; 58 | 59 | bool stop(false); 60 | cv::Mat frame; // current video frame 61 | cv::namedWindow("Extracted Frame"); 62 | 63 | // Delay between each frame 64 | // corresponds to video frame rate 65 | int delay= 1000/rate; 66 | long long i=0; 67 | std::string b="bike"; 68 | std::string ext=".bmp"; 69 | // for all frames in video 70 | while (!stop) { 71 | 72 | // read next frame if any 73 | if (!capture.read(frame)) 74 | break; 75 | 76 | cv::imshow("Extra cted Frame",frame); 77 | 78 | std::string name(b); 79 | // note: some MinGW compilers generate an error for this line 80 | // this is a compiler bug 81 | // try: std::ostringstream ss; ss << i; name+= ss.rdbuf(); i++; 82 | // name+=std::to_string(i++); 83 | std::ostringstream ss; ss << i; name+= ss.str(); i++; 84 | name+=ext; 85 | 86 | std::cout << name <=0) 93 | stop= true; 94 | } 95 | 96 | // Close the video file 97 | capture.release(); 98 | 99 | cv::waitKey(); 100 | 101 | // Now using the VideoProcessor class 102 | 103 | // Create instance 104 | VideoProcessor processor; 105 | 106 | // Open video file 107 | processor.setInput("bike.avi"); 108 | 109 | // Declare a window to display the video 110 | processor.displayInput("Input Video"); 111 | processor.displayOutput("Output Video"); 112 | 113 | // Play the video at the original frame rate 114 | processor.setDelay(1000./processor.getFrameRate()); 115 | 116 | // Set the frame processor callback function 117 | processor.setFrameProcessor(canny); 118 | 119 | // output a video 120 | processor.setOutput("bikeCanny.avi",-1,15); 121 | 122 | // stop the process at this frame 123 | processor.stopAtFrameNo(51); 124 | 125 | // Start the process 126 | processor.run(); 127 | 128 | cv::waitKey(); 129 | 130 | return 0; 131 | } 132 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | These file contains material supporting the cookbook: 2 | Computer Vision Programming using the OpenCV Library. 3 | Second Edition 4 | by Robert Laganiere, Packt Publishing, 2013. 5 | 6 | These programs are free software; permission is hereby granted to use, copy, modify, 7 | and distribute this source code, or portions thereof, for any purpose, without fee, 8 | subject to the restriction that the copyright notice may not be removed 9 | or altered from any source or altered source distribution. 10 | The software is released on an as-is basis and without any warranties of any kind. 11 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. 12 | The author disclaims all warranties with regard to this software, any use, 13 | and any consequent failure, is purely the responsibility of the user. 14 | 15 | Copyright (C) 2013 Robert Laganiere, www.laganiere.name 16 | --------------------------------------------------------------------------------