|
@@ -1,64 +1,109 @@
|
|
-#include "opencv2/highgui/highgui.hpp"
|
|
|
|
-#include "opencv2/imgproc/imgproc.hpp"
|
|
|
|
-#include "opencv2/imgcodecs.hpp"
|
|
|
|
|
|
+
|
|
|
|
+#include <opencv2/imgproc.hpp>
|
|
|
|
+#include <opencv2/highgui.hpp>
|
|
|
|
+#include <opencv2/opencv.hpp>
|
|
|
|
+
|
|
|
|
+#include <vector>
|
|
|
|
+#include <algorithm>
|
|
|
|
+#include <tuple>
|
|
#include <iostream>
|
|
#include <iostream>
|
|
-#include <stdio.h>
|
|
|
|
-#include <stdlib.h>
|
|
|
|
|
|
+
|
|
|
|
|
|
using namespace cv;
|
|
using namespace cv;
|
|
-using namespace std;
|
|
|
|
|
|
|
|
-Mat src; Mat src_gray;
|
|
|
|
-int thresh = 100;
|
|
|
|
-int max_thresh = 255;
|
|
|
|
-RNG rng(12345);
|
|
|
|
|
|
|
|
-/// Function header
|
|
|
|
-void thresh_callback(int, void* );
|
|
|
|
|
|
+struct comparator{
|
|
|
|
+ bool operator() (std::tuple<std::vector<cv::Point>, bool, double> t1,
|
|
|
|
+ std::tuple<std::vector<cv::Point>, bool, double> t2) {
|
|
|
|
+ return std::get<2>(t1) > std::get<2>(t2);
|
|
|
|
+ }
|
|
|
|
+} comparator;
|
|
|
|
|
|
-/** @function main */
|
|
|
|
-int main( int argc, char** argv )
|
|
|
|
|
|
+int main(int, char**)
|
|
{
|
|
{
|
|
- /// Load source image and convert it to gray
|
|
|
|
- src = imread( "C:\\Users\\Sky\\Downloads\\1.jpg", IMREAD_COLOR );
|
|
|
|
|
|
+ // get image
|
|
|
|
+ cv::Mat image = cv::imread("C:\\Users\\Sky\\Downloads\\name.png");
|
|
|
|
+ cv::Mat grayImg;
|
|
|
|
|
|
- /// Convert image to gray and blur it
|
|
|
|
- cvtColor( src, src_gray, COLOR_BGR2GRAY );
|
|
|
|
- blur( src_gray, src_gray, Size(3,3) );
|
|
|
|
|
|
+ // convert to greyscale
|
|
|
|
+ cv::cvtColor(image, grayImg, COLOR_BGRA2GRAY);
|
|
|
|
|
|
- /// Create Window
|
|
|
|
- char* source_window = "Source";
|
|
|
|
- namedWindow( source_window, WINDOW_AUTOSIZE );
|
|
|
|
- imshow( source_window, src );
|
|
|
|
|
|
+// cv::Mat canny;
|
|
|
|
+// cv::Canny(grayImg,canny, 120, 255, 3);
|
|
|
|
|
|
- createTrackbar( " Canny thresh:", "Source", &thresh, max_thresh, thresh_callback );
|
|
|
|
- thresh_callback( 0, 0 );
|
|
|
|
|
|
+ // finding threshes
|
|
|
|
+ cv::Mat thresh;
|
|
|
|
+ cv::threshold(grayImg,thresh, 127, 255, THRESH_BINARY_INV | THRESH_OTSU);
|
|
|
|
|
|
- waitKey(0);
|
|
|
|
- return(0);
|
|
|
|
-}
|
|
|
|
|
|
|
|
-/** @function thresh_callback */
|
|
|
|
-void thresh_callback(int, void* )
|
|
|
|
-{
|
|
|
|
- Mat canny_output;
|
|
|
|
- vector<vector<Point> > contours;
|
|
|
|
- vector<Vec4i> hierarchy;
|
|
|
|
-
|
|
|
|
- /// Detect edges using canny
|
|
|
|
- Canny( src_gray, canny_output, thresh, thresh*2, 3 );
|
|
|
|
- /// Find contours
|
|
|
|
- findContours( canny_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );
|
|
|
|
-
|
|
|
|
- /// Draw contours
|
|
|
|
- Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );
|
|
|
|
- for( int i = 0; i < contours.size(); i++ )
|
|
|
|
- {
|
|
|
|
- Scalar color = Scalar( rng.uniform(255, 255), rng.uniform(255,255), rng.uniform(255,255) );
|
|
|
|
- drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /// Show in a window
|
|
|
|
- namedWindow( "Contours", WINDOW_AUTOSIZE );
|
|
|
|
- imshow( "Contours", drawing );
|
|
|
|
|
|
+ // finding contours
|
|
|
|
+ std::vector<std::vector<cv::Point>> contours;
|
|
|
|
+ std::vector<cv::Vec4i> hierarchy;
|
|
|
|
+
|
|
|
|
+ findContours( thresh, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0) );
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // finding max contour
|
|
|
|
+ std::vector<std::tuple<std::vector<cv::Point>, bool, double>> vec;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ for(size_t i = 0; i < contours.size(); ++i){
|
|
|
|
+
|
|
|
|
+ vec.push_back(std::make_tuple(contours.at(i), cv::isContourConvex(contours.at(i)),cv::contourArea(contours.at(i))));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ std::sort(vec.begin(), vec.end(), comparator);
|
|
|
|
+
|
|
|
|
+ std::tuple<std::vector<cv::Point>, bool, double> maxContour;
|
|
|
|
+ maxContour = vec.at(0);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // create mask
|
|
|
|
+ cv::Mat mask = Mat::zeros(thresh.size(), CV_8U);
|
|
|
|
+
|
|
|
|
+ for(size_t i = 0; i < contours.size(); ++i){
|
|
|
|
+ cv::fillConvexPoly(mask, std::get<0>(vec.at(i)), Scalar(255,0,0),8,0);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+// cv::fillConvexPoly(mask, std::get<0>(maxContour), Scalar(255,0,0),8,0);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // bitwise
|
|
|
|
+ cv::Mat res;
|
|
|
|
+ cv::bitwise_and(image, image, res, mask);
|
|
|
|
+
|
|
|
|
+ // show process
|
|
|
|
+ imshow("result", res);
|
|
|
|
+ imshow("mask", mask);
|
|
|
|
+ imshow("canny", thresh);
|
|
|
|
+ imshow("source", image);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // create transparent background
|
|
|
|
+ Mat dst;
|
|
|
|
+
|
|
|
|
+ Mat rgb[3];
|
|
|
|
+ split(res,rgb);
|
|
|
|
+
|
|
|
|
+ Mat rgba[4]={rgb[0],rgb[1],rgb[2], mask};
|
|
|
|
+ merge(rgba,4,dst);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // save to file transparent and cropped images
|
|
|
|
+ imwrite("C:/Documents/1.png", res);
|
|
|
|
+ imwrite("C:/Documents/dst.png",dst);
|
|
|
|
+ imwrite("C:/Documents/mask.png",mask);
|
|
|
|
+ imwrite("C:/Documents/thresh.png",thresh);
|
|
|
|
+ imwrite("C:/Documents/src.png",image);
|
|
|
|
+
|
|
|
|
+ while (true) {
|
|
|
|
+ if (waitKey() == 27) { //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
|
|
|
|
+ std::cout << "esc key is pressed by user";
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
}
|
|
}
|