使用opencv从二进制图像中删除半曲面对象

to remove a semi-curved object from a binary image using opencv

我有一个二值图像:

我想从图像中删除底部的两个新月形状(大小和面积可能会因图像而异)或至少将其与其余部分区分开来。 我尝试了 Hough 圆变换来检测曲线,因为它类似于圆的一部分,但该代码不起作用:

int main(int argc, char** argv)
{
   Mat src, gray;


    src = imread("446.bmp", 1);             
    namedWindow("src", 1);
    imshow("src", src);
    waitKey(0);

    cvtColor(src, gray, CV_BGR2GRAY);       
    // Reduce the noise so we avoid false circle detection
    GaussianBlur(gray, gray, Size(9, 9), 2, 2);

    vector<Vec3f> circles;

    // Apply the Hough Transform to find the circles
    HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 1, 30, 100, 100, 0, 0);

    // Draw the circles detected
    for (size_t i = 0; i < circles.size(); i++)
    {
        Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
        int radius = cvRound(circles[i][2]);
        circle(src, center, 3, Scalar(0, 255, 0), -1, 8, 0);// circle center     
        circle(src, center, radius, Scalar(0, 0, 255), 3, 8, 0);// circle outline
        cout << "center : " << center << "\nradius : " << radius << endl;
    }

    // Show your results
    namedWindow("Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE);
    imshow("Hough Circle Transform Demo", src);

    waitKey(0);
    return 0;

}

但是没有画圆或者根本没有检测到新月形状。知道我哪里出错了吗?

编辑 1- 我也添加了一些其他图片:

Edit-2 要尝试的新图像:-

不幸的是,我认为这里没有简单的解决方案。

您可能想尝试 detect and label each image component. From here you need to detect which set of pixels looks like a crescent and which does not : as a crescent can be described by a polynomial equations you only need to describe each component (i.e a set of points) as a mathematical equation (using regression methods such as RANSAC) 看看这是否可能是新月方程。

我对代码做了一些修改posted for other question

你可以试试

#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"

using namespace cv;
using namespace std;

//! Compute the distance between two points
/*! Compute the Euclidean distance between two points
*
* @param a Point a
* @param b Point b
*/
static double distanceBtwPoints(const cv::Point2f &a, const cv::Point2f &b)
{
    double xDiff = a.x - b.x;
    double yDiff = a.y - b.y;

    return std::sqrt((xDiff * xDiff) + (yDiff * yDiff));
}

int main( int argc, char** argv )
{
    Mat src,gray;
    src = imread(argv[1]);
    if(src.empty())
        return -1;

    cvtColor( src, gray, COLOR_BGR2GRAY );
    gray = gray < 200;

    vector<vector<Point> > contours;

    findContours(gray.clone(), contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

    RotatedRect _minAreaRect;

    for (size_t i = 0; i < contours.size(); ++i)
    {

        double contour_area = contourArea(contours[i]);
        _minAreaRect = minAreaRect( Mat(contours[i]) );
        Point2f pts[4];
        _minAreaRect.points(pts);

        double dist0 = distanceBtwPoints(pts[0], pts[1]);
        double dist1 = distanceBtwPoints(pts[1], pts[2]);

        double angle = 0;
        //if(dist0 > dist1 *1.2)
        angle =atan2(pts[0].y - pts[1].y,pts[0].x - pts[1].x) * 180.0 / CV_PI;
        //if(dist1 > dist0 *1.2)
        angle =atan2(pts[1].y - pts[2].y,pts[1].x - pts[2].x) * 180.0 / CV_PI;

        if( fabs(angle) > 91 ) // you can try different values
        {
            if( contour_area < dist0 * dist1 /2 ) // you can try different values
            {
                //drawContours(src,contours,i,Scalar(0,0,0),-1); // try to uncomment this line
                for( int j = 0; j < 4; j++ )
                    line(src, pts[j], pts[(j+1)%4], Scalar(0, 0, 255), 1, LINE_AA);
            }
        }
    }
    imshow("result", src);
    waitKey(0);
    return 0;
}