直接找到该图像中的椭圆可能非常棘手。但是,您可以查看 here 以获取一些信息和代码参考。
在这种情况下,分割 3 种颜色要容易得多:blue、red 和 yellow,找到外轮廓,然后拟合对他们来说是一个椭圆。
所以,在这个输入图像上:
因此,您首先将图像转换为 HSV,然后应用一些阈值来恢复蒙版。使用形态学 close 操作将摆脱一些 hole,并链接附近的 blob。
蓝色面具:
红色面具:
黄色面具:
然后,您可以从此掩码中检索外部轮廓,并仅保留最大的(以防您发现一些不属于目标的较小斑点)。
现在你只需要为这些轮廓拟合一个椭圆:
请注意,我也在图像in your other question 上进行了尝试。蓝色目标是变形的,所以不是椭圆,所以在这里拟合椭圆不是一个好的选择:
在这种情况下可能会更好地使用轮廓的凸包,如果遮罩不完美,它会比轮廓本身更健壮(代码如下):
代码:
#include <opencv2/opencv.hpp>
#include <vector>
#include <string>
using namespace std;
using namespace cv;
int main()
{
// Load image
Mat3b img = imread("path_to_image");
// Convert to hsv
Mat3b hsv;
cvtColor(img, hsv, COLOR_BGR2HSV);
// Find masks for different colors
Mat1b blue_mask;
inRange(hsv, Scalar(90, 150, 150), Scalar(110, 255, 255), blue_mask);
Mat1b red_mask;
inRange(hsv, Scalar(160, 150, 100), Scalar(180, 255, 255), red_mask);
Mat1b yellow_mask;
inRange(hsv, Scalar(20, 150, 100), Scalar(30, 255, 255), yellow_mask);
// Apply morphological close
Mat1b kernel = getStructuringElement(MORPH_ELLIPSE, Size(11,11));
morphologyEx(blue_mask, blue_mask, MORPH_CLOSE, kernel);
morphologyEx(red_mask, red_mask, MORPH_CLOSE, kernel);
morphologyEx(yellow_mask, yellow_mask, MORPH_CLOSE, kernel);
// Find largest blob and draw it
vector<Point> blue_contour, red_contour, yellow_contour;
{
vector<vector<Point>> contours;
findContours(blue_mask.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
blue_contour = *max_element(contours.begin(), contours.end(), [](const vector<Point>& lhs, const vector<Point>& rhs){
return contourArea(lhs) < contourArea(rhs); });
}
{
vector<vector<Point>> contours;
findContours(red_mask.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
red_contour = *max_element(contours.begin(), contours.end(), [](const vector<Point>& lhs, const vector<Point>& rhs){
return contourArea(lhs) < contourArea(rhs); });
}
{
vector<vector<Point>> contours;
findContours(yellow_mask.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
yellow_contour = *max_element(contours.begin(), contours.end(), [](const vector<Point>& lhs, const vector<Point>& rhs){
return contourArea(lhs) < contourArea(rhs); });
}
// Fit ellipse
RotatedRect blue_ellipse = fitEllipse(blue_contour);
RotatedRect red_ellipse = fitEllipse(red_contour);
RotatedRect yellow_ellipse = fitEllipse(yellow_contour);
// Draw ellipses
ellipse(img, blue_ellipse, Scalar(255, 0, 0), 3);
ellipse(img, red_ellipse, Scalar(0, 0, 255), 3);
ellipse(img, yellow_ellipse, Scalar(0, 255, 255), 3);
imshow("Result", img);
waitKey();
return 0;
}
凸包代码:
// Get convex hulls
vector<Point> blue_hull, red_hull, yellow_hull;
convexHull(blue_contour, blue_hull);
convexHull(red_contour, red_hull);
convexHull(yellow_contour, yellow_hull);
// Draw convex hulls
drawContours(img, vector < vector<Point> > {blue_hull}, 0, Scalar(255,0,0), 3);
drawContours(img, vector < vector<Point> > {red_hull}, 0, Scalar(0, 0, 255), 3);
drawContours(img, vector < vector<Point> > {yellow_hull}, 0, Scalar(0, 255, 255), 3);