如何使用opencv删除房子的边缘

时间:2017-01-15 08:07:05

标签: image opencv convex-hull

enter image description here

如何删除上图的圆圈内容。原始图像如下所示: enter image description here

1 个答案:

答案 0 :(得分:0)

#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;
}