diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e5ed59..1decf2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,13 @@ add_executable( example_11-02 example_11-02.cpp ) add_executable( example_11-03 example_11-03.cpp ) add_executable( example_12-01 example_12-01.cpp ) add_executable( example_12-02 example_12-02.cpp ) +add_executable( example_13-01 example_13-01.cpp ) +add_executable( example_13-02 example_13-02.cpp ) +add_executable( example_13-03 example_13-03.cpp ) +add_executable( example_14-01 example_14-01.cpp ) +add_executable( example_14-02 example_14-02.cpp ) +add_executable( example_14-03 example_14-03.cpp ) +add_executable( example_14-04 example_14-04.cpp ) add_executable( example_16-01 example_16-01.cpp ) target_link_libraries( example_02-01 ${OpenCV_LIBS} ) @@ -75,8 +82,11 @@ target_link_libraries( example_11-02 ${OpenCV_LIBS} ) target_link_libraries( example_11-03 ${OpenCV_LIBS} ) target_link_libraries( example_12-01 ${OpenCV_LIBS} ) target_link_libraries( example_12-02 ${OpenCV_LIBS} ) +target_link_libraries( example_13-01 ${OpenCV_LIBS} ) +target_link_libraries( example_13-02 ${OpenCV_LIBS} ) +target_link_libraries( example_13-03 ${OpenCV_LIBS} ) +target_link_libraries( example_14-01 ${OpenCV_LIBS} ) +target_link_libraries( example_14-02 ${OpenCV_LIBS} ) +target_link_libraries( example_14-03 ${OpenCV_LIBS} ) +target_link_libraries( example_14-04 ${OpenCV_LIBS} ) target_link_libraries( example_16-01 ${OpenCV_LIBS} ) - - - - diff --git a/HandIndoorColor.jpg b/HandIndoorColor.jpg new file mode 100644 index 0000000..32427bb Binary files /dev/null and b/HandIndoorColor.jpg differ diff --git a/HandOutdoorColor.jpg b/HandOutdoorColor.jpg new file mode 100644 index 0000000..5a3c2d8 Binary files /dev/null and b/HandOutdoorColor.jpg differ diff --git a/HandOutdoorSunColor.jpg b/HandOutdoorSunColor.jpg new file mode 100644 index 0000000..a35f5f6 Binary files /dev/null and b/HandOutdoorSunColor.jpg differ diff --git a/example_13-01.cpp b/example_13-01.cpp new file mode 100644 index 0000000..d727222 --- /dev/null +++ b/example_13-01.cpp @@ -0,0 +1,55 @@ +// Example 13-1. Histogram computation and display + +#include +#include + +using namespace std; + +int main( int argc, char** argv ){ + if(argc != 2) { + cout << "Computer Color Histogram\nUsage: " <" << endl; + return -1; + } + + cv::Mat src = cv::imread( argv[1],1 ); + if( src.empty() ) { cout << "Cannot load " << argv[1] << endl; return -1; } + + // Compute the HSV image, and decompose it into separate planes. + // + cv::Mat hsv; + cv::cvtColor(src, hsv, cv::COLOR_BGR2HSV); + + float h_ranges[] = {0, 180}; // hue is [0, 180] + float s_ranges[] = {0, 256}; + const float* ranges[] = {h_ranges, s_ranges}; + int histSize[] = {30, 32}, ch[] = {0, 1}; + + cv::Mat hist; + + // Compute the histogram + // + cv::calcHist(&hsv, 1, ch, cv::noArray(), hist, 2, histSize, ranges, true); + cv::normalize(hist, hist, 0, 255, cv::NORM_MINMAX); + + int scale = 10; + cv::Mat hist_img(histSize[0]*scale, histSize[1]*scale, CV_8UC3); + + // Draw our histogram. + // + for( int h = 0; h < histSize[0]; h++ ) { + for( int s = 0; s < histSize[1]; s++ ){ + float hval = hist.at(h, s); + cv::rectangle( + hist_img, + cv::Rect(h*scale,s*scale,scale,scale), + cv::Scalar::all(hval), + -1 + ); + } + } + + cv::imshow("image", src); + cv::imshow("H-S histogram", hist_img); + cv::waitKey(); + return 0; +} diff --git a/example_13-02.cpp b/example_13-02.cpp new file mode 100644 index 0000000..089ad89 --- /dev/null +++ b/example_13-02.cpp @@ -0,0 +1,162 @@ +// Example 13-2. Creating signatures from histograms for EMD; note that this code is the +// source of the data in Table 13-1, in which the hand histogram is compared in different +// lighting conditions + +#include +#include + +using namespace std; + +void help( char** argv ){ + cout << "\nCall is:\n" + << argv[0] <<" modelImage0 testImage1 testImage2 badImage3\n\n" + << "for example: " << argv[0] + << " HandIndoorColor.jpg HandOutdoorColor.jpg " + << "HandOutdoorSunColor.jpg fruits.jpg\n" + << "\n"; +} + +// Compare 3 images' histograms +int main( int argc, char** argv ) { + if( argc != 5 ) { help( argv ); return -1; } + vector src(5); + cv::Mat tmp; + int i; + + tmp = cv::imread( argv[1], 1); + if( tmp.empty() ) { + cerr << "Error on reading image 1," << argv[1] << "\n" << endl; + help( argv ); + return(-1); + } + + // Parse the first image into two image halves divided halfway on y + // + cv::Size size = tmp.size(); + int width = size.width; + int height = size.height; + int halfheight = height >> 1; + + cout <<"Getting size [[" <::iterator tmpit = tmp.begin(); + + // top half + // + cv::Mat_::iterator s0it = src[0].begin(); + for(i = 0; i < width*halfheight; ++i, ++tmpit, ++s0it) *s0it = *tmpit; + + // Bottom half + // + cv::Mat_::iterator s1it = src[1].begin(); + for(i = 0; i < width*halfheight; ++i, ++tmpit, ++s1it) *s1it = *tmpit; + + // Load the other three images + // + for(i = 2; i<5; ++i){ + src[i] = cv::imread(argv[i], 1); + if(src[i].empty()) { + cerr << "Error on reading image " << i << ": " << argv[i] << "\n" << endl; + help( argv ); + return(-1); + } + } + + // Compute the HSV image, and decompose it into separate planes. + // + vector hsv(5), hist(5), hist_img(5); + int h_bins = 8; + int s_bins = 8; + int hist_size[] = { h_bins, s_bins }, ch[] = {0, 1}; + float h_ranges[] = { 0, 180 }; // hue range is [0,180] + float s_ranges[] = { 0, 255 }; + const float* ranges[] = { h_ranges, s_ranges }; + int scale = 10; + + for(i = 0; i<5; ++i) { + cv::cvtColor( src[i], hsv[i], cv::COLOR_BGR2HSV ); + cv::calcHist( &hsv[i], 1, ch, cv::noArray(), hist[i], 2, hist_size, ranges, true ); + cv::normalize( hist[i], hist[i], 0, 255, cv::NORM_MINMAX ); + hist_img[i] = cv::Mat::zeros( hist_size[0]*scale, hist_size[1]*scale, CV_8UC3 ); + + // Draw our histogram For the 5 images + // + for( int h = 0; h < hist_size[0]; h++ ) + for( int s = 0; s < hist_size[1]; s++ ) { + float hval = hist[i].at(h, s); + cv::rectangle( + hist_img[i], + cv::Rect(h*scale, s*scale, scale, scale), + cv::Scalar::all(hval), + -1 + ); + } + } + + // Display + // + cv::namedWindow( "Source0", 1 );cv::imshow( "Source0", src[0] ); + cv::namedWindow( "HS Histogram0", 1 );cv::imshow( "HS Histogram0", hist_img[0] ); + + cv::namedWindow( "Source1", 1 );cv::imshow( "Source1", src[1] ); + cv::namedWindow( "HS Histogram1", 1 ); cv::imshow( "HS Histogram1", hist_img[1] ); + + cv::namedWindow( "Source2", 1 ); cv::imshow( "Source2", src[2] ); + cv::namedWindow( "HS Histogram2", 1 ); cv::imshow( "HS Histogram2", hist_img[2] ); + + cv::namedWindow( "Source3", 1 ); cv::imshow( "Source3", src[3] ); + cv::namedWindow( "HS Histogram3", 1 ); cv::imshow( "HS Histogram3", hist_img[3] ); + + cv::namedWindow( "Source4", 1 ); cv::imshow( "Source4", src[4] ); + cv::namedWindow( "HS Histogram4", 1 ); cv::imshow( "HS Histogram4", hist_img[4] ); + + // Compare the histogram src0 vs 1, vs 2, vs 3, vs 4 + cout << "Comparison:\n" + << "Corr Chi Intersect Bhat\n"<< endl; + + for(i=1; i<5; ++i) { // For each histogram + cout << "Hist[0] vs Hist[" << i << "]: " << endl;; + for(int j=0; j<4; ++j) { // For each comparison type + cout << "method[" << j << "]: " << cv::compareHist(hist[0],hist[i],j) << " "; + } + cout << endl; + } + + //Do EMD and report + // + vector sig(5); + cout << "\nEMD: " << endl; + + // Oi Vey, parse histograms to earth movers signatures + // + for( i=0; i<5; ++i) { + + vector sigv; + + // (re)normalize histogram to make the bin weights sum to 1. + // + cv::normalize(hist[i], hist[i], 1, 0, cv::NORM_L1); + for( int h = 0; h < h_bins; h++ ) + for( int s = 0; s < s_bins; s++ ) { + float bin_val = hist[i].at(h, s); + if( bin_val != 0 ) + sigv.push_back( cv::Vec3f(bin_val, (float)h, (float)s)); + } + + // make Nx3 32fC1 matrix, where N is the number of nonzero histogram bins + // + sig[i] = cv::Mat(sigv).clone().reshape(1); + if( i > 0 ) + cout << "Hist[0] vs Hist[" << i << "]: " + << EMD(sig[0], sig[i], cv::DIST_L2) << endl; + } + + cv::waitKey(0); + +} diff --git a/example_13-03.cpp b/example_13-03.cpp new file mode 100644 index 0000000..d6dedf3 --- /dev/null +++ b/example_13-03.cpp @@ -0,0 +1,70 @@ +// Example 13-3. Template matching + +#include +#include + +using namespace std; + +void help( char** argv ){ + cout << "\n" + <<"Example of using matchTemplate(). The call is:\n" + <<"\n" + < +#include + +using namespace std; + +cv::Mat g_gray, g_binary; +int g_thresh = 100; + +void on_trackbar( int, void* ) { + cv::threshold( g_gray, g_binary, g_thresh, 255, cv::THRESH_BINARY ); + vector< vector< cv::Point> > contours; + cv::findContours( + g_binary, + contours, + cv::noArray(), + cv::RETR_LIST, + cv::CHAIN_APPROX_SIMPLE + ); + g_binary = cv::Scalar::all(0); + + cv::drawContours( g_binary, contours, -1, cv::Scalar::all(255)); + cv::imshow( "Contours", g_binary ); + +} + +int main( int argc, char** argv ) { + if( argc != 2 || ( g_gray = cv::imread(argv[1], 0)).empty() ) { + cout << "Find threshold dependent contours\nUsage: " < +#include +#include + +using namespace std; + +struct AreaCmp { + AreaCmp(const vector& _areas) : areas(&_areas) {} + bool operator()(int a, int b) const { return (*areas)[a] > (*areas)[b]; } + const vector* areas; +}; + +int main(int argc, char* argv[]) { + + cv::Mat img, img_edge, img_color; + + // load image or show help if no image was provided + // + if( argc != 2 || (img = cv::imread(argv[1],cv::IMREAD_GRAYSCALE)).empty() ) { + cout << "\nExample 14_2 Drawing Contours\nCall is:\n" << argv[0] << " image\n\n"; + return -1; + } + + cv::threshold(img, img_edge, 128, 255, cv::THRESH_BINARY); + cv::imshow("Image after threshold", img_edge); + vector< vector< cv::Point > > contours; + vector< cv::Vec4i > hierarchy; + + cv::findContours( + img_edge, + contours, + hierarchy, + cv::RETR_LIST, + cv::CHAIN_APPROX_SIMPLE + ); + cout << "\n\nHit any key to draw the next contour, ESC to quit\n\n"; + cout << "Total Contours Detected: " << contours.size() << endl; + + vector sortIdx(contours.size()); + vector areas(contours.size()); + for( int n = 0; n < (int)contours.size(); n++ ) { + sortIdx[n] = n; + areas[n] = contourArea(contours[n], false); + } + + // sort contours so that the largest contours go first + // + std::sort( sortIdx.begin(), sortIdx.end(), AreaCmp(areas )); + + for( int n = 0; n < (int)sortIdx.size(); n++ ) { + int idx = sortIdx[n]; + cv::cvtColor( img, img_color, cv::COLOR_GRAY2BGR ); + cv::drawContours( + img_color, contours, idx, + cv::Scalar(0,0,255), 2, 8, hierarchy, + 0 // Try different values of max_level, and see what happens + ); + cout << "Contour #" << idx << ": area=" << areas[idx] << + ", nvertices=" << contours[idx].size() << endl; + cv::imshow(argv[0], img_color); + int k; + if( (k = cv::waitKey()&255) == 27 ) + break; + } + cout << "Finished all contours\n"; + + return 0; +} diff --git a/example_14-03.cpp b/example_14-03.cpp new file mode 100644 index 0000000..1dd3d23 --- /dev/null +++ b/example_14-03.cpp @@ -0,0 +1,51 @@ +// Example 14-3. Drawing labeled connected components + +#include +#include +#include + +using namespace std; + +int main(int argc, char* argv[]) { + + cv::Mat img, img_edge, labels, img_color, stats; + + // load image or show help if no image was provided + if( argc != 2 + || (img = cv::imread( argv[1], cv::IMREAD_GRAYSCALE )).empty() + ) { + cout << "\nExample 8_3 Drawing Connected componnents\n" \ + << "Call is:\n" < colors(nccomps+1); + colors[0] = cv::Vec3b(0,0,0); // background pixels remain black. + for( i = 1; i <= nccomps; i++ ) { + colors[i] = cv::Vec3b(rand()%256, rand()%256, rand()%256); + if( stats.at(i-1, cv::CC_STAT_AREA) < 100 ) + colors[i] = cv::Vec3b(0,0,0); // small regions are painted with black too. + } + img_color = cv::Mat::zeros(img.size(), CV_8UC3); + for( int y = 0; y < img_color.rows; y++ ) + for( int x = 0; x < img_color.cols; x++ ) + { + int label = labels.at(y, x); + CV_Assert(0 <= label && label <= nccomps); + img_color.at(y, x) = colors[label]; + } + + cv::imshow("Labeled map", img_color); + cv::waitKey(); + return 0; +} + diff --git a/example_14-04.cpp b/example_14-04.cpp new file mode 100644 index 0000000..c2b148f --- /dev/null +++ b/example_14-04.cpp @@ -0,0 +1,54 @@ +// Example 14-4. Using the shape context distance extractor + +#include +#include +#include + +#include "opencv2/opencv.hpp" + +using namespace std; +using namespace cv; + +static vector sampleContour( const Mat& image, int n=300 ) { + + vector > _contours; + vector all_points; + findContours(image, _contours, RETR_LIST, CHAIN_APPROX_NONE); + for (size_t i=0; i <_contours.size(); i++) { + for (size_t j=0; j <_contours[i].size(); j++) + all_points.push_back( _contours[i][j] ); + + // If too little points, replicate them + // + int dummy=0; + for (int add=(int)all_points.size(); add sampled; + for (int i=0; i mysc = createShapeContextDistanceExtractor(); + + Size sz2Sh(300,300); + Mat img1=imread(argv[1], IMREAD_GRAYSCALE); + Mat img2=imread(argv[2], IMREAD_GRAYSCALE); + vector c1 = sampleContour(img1); + vector c2 = sampleContour(img2); + float dis = mysc->computeDistance( c1, c2 ); + cout << "shape context distance between " << + argv[1] << " and " << argv[2] << " is: " << dis << endl; + + return 0; + +} diff --git a/faceScene.jpg b/faceScene.jpg new file mode 100644 index 0000000..670592d Binary files /dev/null and b/faceScene.jpg differ diff --git a/faceTemplate.jpg b/faceTemplate.jpg new file mode 100644 index 0000000..1006387 Binary files /dev/null and b/faceTemplate.jpg differ diff --git a/fruits.jpg b/fruits.jpg new file mode 100644 index 0000000..a89b84a Binary files /dev/null and b/fruits.jpg differ diff --git a/shape_sample/1.png b/shape_sample/1.png new file mode 100644 index 0000000..f473cb4 Binary files /dev/null and b/shape_sample/1.png differ diff --git a/shape_sample/10.png b/shape_sample/10.png new file mode 100644 index 0000000..46283ca Binary files /dev/null and b/shape_sample/10.png differ diff --git a/shape_sample/11.png b/shape_sample/11.png new file mode 100644 index 0000000..d4f114d Binary files /dev/null and b/shape_sample/11.png differ diff --git a/shape_sample/12.png b/shape_sample/12.png new file mode 100644 index 0000000..ad876e9 Binary files /dev/null and b/shape_sample/12.png differ diff --git a/shape_sample/13.png b/shape_sample/13.png new file mode 100644 index 0000000..2ec2621 Binary files /dev/null and b/shape_sample/13.png differ diff --git a/shape_sample/14.png b/shape_sample/14.png new file mode 100644 index 0000000..956e5b8 Binary files /dev/null and b/shape_sample/14.png differ diff --git a/shape_sample/15.png b/shape_sample/15.png new file mode 100644 index 0000000..422395f Binary files /dev/null and b/shape_sample/15.png differ diff --git a/shape_sample/16.png b/shape_sample/16.png new file mode 100644 index 0000000..57ad410 Binary files /dev/null and b/shape_sample/16.png differ diff --git a/shape_sample/17.png b/shape_sample/17.png new file mode 100644 index 0000000..58417bc Binary files /dev/null and b/shape_sample/17.png differ diff --git a/shape_sample/18.png b/shape_sample/18.png new file mode 100644 index 0000000..25fb50b Binary files /dev/null and b/shape_sample/18.png differ diff --git a/shape_sample/19.png b/shape_sample/19.png new file mode 100644 index 0000000..256b888 Binary files /dev/null and b/shape_sample/19.png differ diff --git a/shape_sample/2.png b/shape_sample/2.png new file mode 100644 index 0000000..7c7c31b Binary files /dev/null and b/shape_sample/2.png differ diff --git a/shape_sample/20.png b/shape_sample/20.png new file mode 100644 index 0000000..de8d5ed Binary files /dev/null and b/shape_sample/20.png differ diff --git a/shape_sample/3.png b/shape_sample/3.png new file mode 100644 index 0000000..7e8f7bc Binary files /dev/null and b/shape_sample/3.png differ diff --git a/shape_sample/4.png b/shape_sample/4.png new file mode 100644 index 0000000..5cced92 Binary files /dev/null and b/shape_sample/4.png differ diff --git a/shape_sample/5.png b/shape_sample/5.png new file mode 100644 index 0000000..786d658 Binary files /dev/null and b/shape_sample/5.png differ diff --git a/shape_sample/6.png b/shape_sample/6.png new file mode 100644 index 0000000..e87cf4d Binary files /dev/null and b/shape_sample/6.png differ diff --git a/shape_sample/7.png b/shape_sample/7.png new file mode 100644 index 0000000..b12aa52 Binary files /dev/null and b/shape_sample/7.png differ diff --git a/shape_sample/8.png b/shape_sample/8.png new file mode 100644 index 0000000..52fff13 Binary files /dev/null and b/shape_sample/8.png differ diff --git a/shape_sample/9.png b/shape_sample/9.png new file mode 100644 index 0000000..a54aa3a Binary files /dev/null and b/shape_sample/9.png differ