[
  {
    "path": ".gitignore",
    "content": "CMakeFiles\nCMakeCache*\n*.cmake\nsquares\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 2.8)\nproject( squares )\nfind_package( OpenCV REQUIRED )\nadd_executable( squares squares.cpp )\ntarget_link_libraries( squares ${OpenCV_LIBS} )"
  },
  {
    "path": "Makefile",
    "content": "# CMAKE generated file: DO NOT EDIT!\n# Generated by \"Unix Makefiles\" Generator, CMake Version 2.8\n\n# Default target executed when no arguments are given to make.\ndefault_target: all\n.PHONY : default_target\n\n#=============================================================================\n# Special targets provided by cmake.\n\n# Disable implicit rules so canonical targets will work.\n.SUFFIXES:\n\n# Remove some rules from gmake that .SUFFIXES does not remove.\nSUFFIXES =\n\n.SUFFIXES: .hpux_make_needs_suffix_list\n\n# Suppress display of executed commands.\n$(VERBOSE).SILENT:\n\n# A target that is always out of date.\ncmake_force:\n.PHONY : cmake_force\n\n#=============================================================================\n# Set environment variables for the build.\n\n# The shell in which to execute make rules.\nSHELL = /bin/sh\n\n# The CMake executable.\nCMAKE_COMMAND = /opt/local/bin/cmake\n\n# The command to remove a file.\nRM = /opt/local/bin/cmake -E remove -f\n\n# Escaping for special characters.\nEQUALS = =\n\n# The program to use to edit the cache.\nCMAKE_EDIT_COMMAND = /opt/local/bin/ccmake\n\n# The top-level source directory on which CMake was run.\nCMAKE_SOURCE_DIR = /Users/alyssa/Documents/playground/C++/opencv\n\n# The top-level build directory on which CMake was run.\nCMAKE_BINARY_DIR = /Users/alyssa/Documents/playground/C++/opencv\n\n#=============================================================================\n# Targets provided globally by CMake.\n\n# Special rule for the target edit_cache\nedit_cache:\n\t@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan \"Running CMake cache editor...\"\n\t/opt/local/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)\n.PHONY : edit_cache\n\n# Special rule for the target edit_cache\nedit_cache/fast: edit_cache\n.PHONY : edit_cache/fast\n\n# Special rule for the target rebuild_cache\nrebuild_cache:\n\t@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan \"Running CMake to regenerate build system...\"\n\t/opt/local/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)\n.PHONY : rebuild_cache\n\n# Special rule for the target rebuild_cache\nrebuild_cache/fast: rebuild_cache\n.PHONY : rebuild_cache/fast\n\n# The main all target\nall: cmake_check_build_system\n\t$(CMAKE_COMMAND) -E cmake_progress_start /Users/alyssa/Documents/playground/C++/opencv/CMakeFiles /Users/alyssa/Documents/playground/C++/opencv/CMakeFiles/progress.marks\n\t$(MAKE) -f CMakeFiles/Makefile2 all\n\t$(CMAKE_COMMAND) -E cmake_progress_start /Users/alyssa/Documents/playground/C++/opencv/CMakeFiles 0\n.PHONY : all\n\n# The main clean target\nclean:\n\t$(MAKE) -f CMakeFiles/Makefile2 clean\n.PHONY : clean\n\n# The main clean target\nclean/fast: clean\n.PHONY : clean/fast\n\n# Prepare targets for installation.\npreinstall: all\n\t$(MAKE) -f CMakeFiles/Makefile2 preinstall\n.PHONY : preinstall\n\n# Prepare targets for installation.\npreinstall/fast:\n\t$(MAKE) -f CMakeFiles/Makefile2 preinstall\n.PHONY : preinstall/fast\n\n# clear depends\ndepend:\n\t$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1\n.PHONY : depend\n\n#=============================================================================\n# Target rules for targets named squares\n\n# Build rule for target.\nsquares: cmake_check_build_system\n\t$(MAKE) -f CMakeFiles/Makefile2 squares\n.PHONY : squares\n\n# fast build rule for target.\nsquares/fast:\n\t$(MAKE) -f CMakeFiles/squares.dir/build.make CMakeFiles/squares.dir/build\n.PHONY : squares/fast\n\nsquares.o: squares.cpp.o\n.PHONY : squares.o\n\n# target to build an object file\nsquares.cpp.o:\n\t$(MAKE) -f CMakeFiles/squares.dir/build.make CMakeFiles/squares.dir/squares.cpp.o\n.PHONY : squares.cpp.o\n\nsquares.i: squares.cpp.i\n.PHONY : squares.i\n\n# target to preprocess a source file\nsquares.cpp.i:\n\t$(MAKE) -f CMakeFiles/squares.dir/build.make CMakeFiles/squares.dir/squares.cpp.i\n.PHONY : squares.cpp.i\n\nsquares.s: squares.cpp.s\n.PHONY : squares.s\n\n# target to generate assembly for a file\nsquares.cpp.s:\n\t$(MAKE) -f CMakeFiles/squares.dir/build.make CMakeFiles/squares.dir/squares.cpp.s\n.PHONY : squares.cpp.s\n\n# Help Target\nhelp:\n\t@echo \"The following are some of the valid targets for this Makefile:\"\n\t@echo \"... all (the default if no target is provided)\"\n\t@echo \"... clean\"\n\t@echo \"... depend\"\n\t@echo \"... edit_cache\"\n\t@echo \"... rebuild_cache\"\n\t@echo \"... squares\"\n\t@echo \"... squares.o\"\n\t@echo \"... squares.i\"\n\t@echo \"... squares.s\"\n.PHONY : help\n\n\n\n#=============================================================================\n# Special targets to cleanup operation of make.\n\n# Special rule to run CMake to check the build system integrity.\n# No rule that depends on this can have commands that come from listfiles\n# because they might be regenerated.\ncmake_check_build_system:\n\t$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0\n.PHONY : cmake_check_build_system\n\n"
  },
  {
    "path": "README.md",
    "content": "# Playing with C++ OpenCV\n\n**Aim:** Find squares in an image\n\n## To compile and run\n\n    > cmake .  \n    > make\n    > ./squares\n\n\n### Sample input and output images in /imgs\n\n\n<img src=\"https://raw.github.com/alyssaq/opencv/master/imgs/2stickies.jpg\" width=\"45%\" /> \n&nbsp;&nbsp;&nbsp; \n<img src=\"https://raw.github.com/alyssaq/opencv/master/imgs/out-2stickies.jpg\" width=\"45%\"/>\n\n<br>\n\n<img src=\"https://raw.github.com/alyssaq/opencv/master/imgs/manyStickies.jpg\" width=\"45%\" /> \n&nbsp;&nbsp;&nbsp; \n<img src=\"https://raw.github.com/alyssaq/opencv/master/imgs/out-manyStickies.jpg\" width=\"45%\"/>\n\n### References - To improve results\n\n* http://stackoverflow.com/questions/8667818/opencv-c-obj-c-detecting-a-sheet-of-paper-square-detection   \n* http://stackoverflow.com/questions/10533233/opencv-c-obj-c-advanced-square-detection    \n* http://stackoverflow.com/questions/14221591/detection-square-opencv-and-c    \n* http://stackoverflow.com/questions/7755647/opencv-extract-area-of-an-image-from-a-vector-of-squares/7756000#7756000    \n* http://stackoverflow.com/questions/13523837/find-corner-of-papers/13532779#13532779    \n* [Automatic perspective correction for quadrilateral objects](https://web.archive.org/web/20160316131624/http://opencv-code.com/tutorials/automatic-perspective-correction-for-quadrilateral-objects/) - [Code on github](https://github.com/bsdnoobz/opencv-code/blob/master/quad-segmentation.cpp)\n* [Detecting simple shapes in an image](https://web.archive.org/web/20150317002418/http://opencv-code.com/tutorials/detecting-simple-shapes-in-an-image/) - [Code on github](https://github.com/bsdnoobz/opencv-code/blob/master/shape-detect.cpp)\n"
  },
  {
    "path": "squares.cpp",
    "content": "// The \"Square Detector\" program.\n// It loads several images sequentially and tries to find squares in\n// each image\n\n#include \"opencv2/core/core.hpp\"\n#include \"opencv2/imgproc/imgproc.hpp\"\n#include \"opencv2/highgui/highgui.hpp\"\n\n#include <iostream>\n#include <math.h>\n#include <string.h>\n\nusing namespace cv;\nusing namespace std;\n\nstatic void help()\n{\n    cout <<\n    \"\\nA program using pyramid scaling, Canny, contours, contour simpification and\\n\"\n    \"memory storage to find squares in a list of images\\n\"\n    \"Returns sequence of squares detected on the image.\\n\"\n    \"the sequence is stored in the specified memory storage\\n\"\n    \"Call:\\n\"\n    \"./squares\\n\"\n    \"Using OpenCV version %s\\n\" << CV_VERSION << \"\\n\" << endl;\n}\n\n\nint thresh = 50, N = 5;\nconst char* wndname = \"Square Detection Demo\";\n\n// helper function:\n// finds a cosine of angle between vectors\n// from pt0->pt1 and from pt0->pt2\nstatic double angle( Point pt1, Point pt2, Point pt0 )\n{\n    double dx1 = pt1.x - pt0.x;\n    double dy1 = pt1.y - pt0.y;\n    double dx2 = pt2.x - pt0.x;\n    double dy2 = pt2.y - pt0.y;\n    return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);\n}\n\n// returns sequence of squares detected on the image.\n// the sequence is stored in the specified memory storage\nstatic void findSquares( const Mat& image, vector<vector<Point> >& squares )\n{\n    squares.clear();\n\n//s    Mat pyr, timg, gray0(image.size(), CV_8U), gray;\n\n    // down-scale and upscale the image to filter out the noise\n    //pyrDown(image, pyr, Size(image.cols/2, image.rows/2));\n    //pyrUp(pyr, timg, image.size());\n\n\n    // blur will enhance edge detection\n    Mat timg(image);\n    medianBlur(image, timg, 9);\n    Mat gray0(timg.size(), CV_8U), gray;\n\n    vector<vector<Point> > contours;\n\n    // find squares in every color plane of the image\n    for( int c = 0; c < 3; c++ )\n    {\n        int ch[] = {c, 0};\n        mixChannels(&timg, 1, &gray0, 1, ch, 1);\n\n        // try several threshold levels\n        for( int l = 0; l < N; l++ )\n        {\n            // hack: use Canny instead of zero threshold level.\n            // Canny helps to catch squares with gradient shading\n            if( l == 0 )\n            {\n                // apply Canny. Take the upper threshold from slider\n                // and set the lower to 0 (which forces edges merging)\n                Canny(gray0, gray, 5, thresh, 5);\n                // dilate canny output to remove potential\n                // holes between edge segments\n                dilate(gray, gray, Mat(), Point(-1,-1));\n            }\n            else\n            {\n                // apply threshold if l!=0:\n                //     tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0\n                gray = gray0 >= (l+1)*255/N;\n            }\n\n            // find contours and store them all as a list\n            findContours(gray, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);\n\n            vector<Point> approx;\n\n            // test each contour\n            for( size_t i = 0; i < contours.size(); i++ )\n            {\n                // approximate contour with accuracy proportional\n                // to the contour perimeter\n                approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);\n\n                // square contours should have 4 vertices after approximation\n                // relatively large area (to filter out noisy contours)\n                // and be convex.\n                // Note: absolute value of an area is used because\n                // area may be positive or negative - in accordance with the\n                // contour orientation\n                if( approx.size() == 4 &&\n                    fabs(contourArea(Mat(approx))) > 1000 &&\n                    isContourConvex(Mat(approx)) )\n                {\n                    double maxCosine = 0;\n\n                    for( int j = 2; j < 5; j++ )\n                    {\n                        // find the maximum cosine of the angle between joint edges\n                        double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));\n                        maxCosine = MAX(maxCosine, cosine);\n                    }\n\n                    // if cosines of all angles are small\n                    // (all angles are ~90 degree) then write quandrange\n                    // vertices to resultant sequence\n                    if( maxCosine < 0.3 )\n                        squares.push_back(approx);\n                }\n            }\n        }\n    }\n}\n\n\n// the function draws all the squares in the image\nstatic void drawSquares( Mat& image, const vector<vector<Point> >& squares )\n{\n    for( size_t i = 0; i < squares.size(); i++ )\n    {\n        const Point* p = &squares[i][0];\n\n        int n = (int)squares[i].size();\n        //dont detect the border\n        if (p-> x > 3 && p->y > 3)\n          polylines(image, &p, &n, 1, true, Scalar(0,255,0), 3, LINE_AA);\n    }\n\n    imshow(wndname, image);\n}\n\n\nint main(int /*argc*/, char** /*argv*/)\n{\n    static const char* names[] = { \"imgs/2Stickies.jpg\", \"imgs/manyStickies.jpg\",0 };\n    help();\n    namedWindow( wndname, 1 );\n    vector<vector<Point> > squares;\n\n    for( int i = 0; names[i] != 0; i++ )\n    {\n        Mat image = imread(names[i], 1);\n        if( image.empty() )\n        {\n            cout << \"Couldn't load \" << names[i] << endl;\n            continue;\n        }\n\n        findSquares(image, squares);\n        drawSquares(image, squares);\n        //imwrite( \"out\", image );\n        int c = waitKey();\n        if( (char)c == 27 )\n            break;\n    }\n\n    return 0;\n}\n"
  }
]