Search code examples
imageopencvconvex-hull

How to remove edge of house using opencv


enter image description here

How to remove the circle content of above image. The original image is showed below: enter image description here


Solution

  • #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include <cmath>
    #include <iostream>
    using namespace cv;
    using namespace std;
    /**
    * Helper function to find a cosine of angle between vectors
    * from pt0->pt1 and pt0->pt2
    */
    static double angle(cv::Point pt1, cv::Point pt2, cv::Point pt0)
    {
        double dx1 = pt1.x - pt0.x;
        double dy1 = pt1.y - pt0.y;
        double dx2 = pt2.x - pt0.x;
        double dy2 = pt2.y - pt0.y;
        return (dx1*dx2 + dy1*dy2) / sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
    }
    
    /**
    * Helper function to display text in the center of a contour
    */
    void setLabel(cv::Mat& im, const std::string label, std::vector<cv::Point>& contour)
    {
        int fontface = cv::FONT_HERSHEY_SIMPLEX;
        double scale = 0.4;
        int thickness = 1;
        int baseline = 0;
    
        cv::Size text = cv::getTextSize(label, fontface, scale, thickness, &baseline);
        cv::Rect r = cv::boundingRect(contour);
    
        cv::Point pt(r.x + ((r.width - text.width) / 2), r.y + ((r.height + text.height) / 2));
        cv::rectangle(im, pt + cv::Point(0, baseline), pt + cv::Point(text.width, -text.height), CV_RGB(255, 0, 255), CV_FILLED);
        cv::putText(im, label, pt, fontface, scale, CV_RGB(0, 0, 0), thickness, 8);
    }
    
    int main()
    {
        //cv::Mat src = cv::imread("polygon.png");
        Mat src = imread("3.bmp");//2.png 3.jpg
        Mat src_copy;
        src.copyTo(src_copy);
        resize(src, src, cvSize(0, 0), 1, 1);
        cout << "src type  " << src.type() << endl;
        Mat mask(src.size(), src.type(), Scalar(0));
        if (src.empty())
            return -1;
    
        // Convert to grayscale
        cv::Mat gray;
        if (src.type() != CV_8UC1)
            cv::cvtColor(src, gray, CV_BGR2GRAY);
    
        // Use Canny instead of threshold to catch squares with gradient shading
        cv::Mat bw;
        cv::Canny(gray, bw, 0, 50, 5);
    
        // Find contours
        std::vector<std::vector<cv::Point> > contours;
        cv::findContours(bw.clone(), contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
    
        drawContours(src, contours, -1, Scalar(0, 255, 0), 2);
        std::vector<cv::Point> approx;
        cv::Mat dst = src.clone();
    
        for (int i = 0; i < contours.size(); i++)
        {
            // Approximate contour with accuracy proportional
            // to the contour perimeter
    
            cv::approxPolyDP(cv::Mat(contours[i]), approx, cv::arcLength(cv::Mat(contours[i]), true)*0.1, true);
    
            // Skip small or non-convex objects 
            if (std::fabs(cv::contourArea(contours[i])) < 500 || !cv::isContourConvex(approx))
                continue;
    
            if (approx.size() == 3)
            {
                //setLabel(dst, "TRI", contours[i]);    // Triangles
            }
            else if (approx.size() >= 4 && approx.size() <= 6)
            {
                // Number of vertices of polygonal curve
                int vtc = approx.size();
    
                // Get the cosines of all corners
                std::vector<double> cos;
                for (int j = 2; j < vtc + 1; j++)
                    cos.push_back(angle(approx[j%vtc], approx[j - 2], approx[j - 1]));
    
                // Sort ascending the cosine values
                std::sort(cos.begin(), cos.end());
    
                // Get the lowest and the highest cosine
                double mincos = cos.front();
                double maxcos = cos.back();
    
                // Use the degrees obtained above and the number of vertices
                // to determine the shape of the contour
                if (vtc == 4 && mincos >= -0.2 && maxcos <= 0.5)
                {
                    Mat element = getStructuringElement(MORPH_RECT, Size(13, 13));
                    setLabel(dst, "RECT", contours[i]);
                    drawContours(mask, contours, i, Scalar(255, 255, 255), CV_FILLED);
                    dilate(mask, mask, element);
                    src_copy = src_copy - mask;
                }
    
                else if (vtc == 5 && mincos >= -0.34 && maxcos <= -0.27)
                    setLabel(dst, "PENTA", contours[i]);
                else if (vtc == 6 && mincos >= -0.55 && maxcos <= -0.45)
                    setLabel(dst, "HEXA", contours[i]);
            }
            else
            {
                // Detect and label circles
                double area = cv::contourArea(contours[i]);
                cv::Rect r = cv::boundingRect(contours[i]);
                int radius = r.width / 2;
    
                if (std::abs(1 - ((double)r.width / r.height)) <= 0.2 &&
                    std::abs(1 - (area / (CV_PI * std::pow(radius, 2)))) <= 0.2)
                    setLabel(dst, "CIR", contours[i]);
            }
        }
    
        //cv::imshow("src", src);
        imwrite("mask.jpg", mask);
        imwrite("src.jpg", src_copy);
        imwrite("dst.jpg", dst);
        cv::imshow("dst", dst);
        cv::waitKey(0);
        return 0;
    }