我想用它的颜色检测一个射箭目标并使它达到目的:
原始图像和分析的颜色:
我在RGB图像上使用颜色范围获取圆圈。正如您所看到的,图像上还有许多其他斑点,我想摆脱它们。
我尝试将所有三个图像中的所有形状相互比较,以找到matchShape的最佳匹配,但它不会产生我想要的那三个圆圈。
任何想法如何找出图像上的轮廓/形状/物体实际上是三个圆圈?
输入图片可能有角度/透视,因此我无法使用霍夫找到圆圈。
我需要的是三个圆的轮廓(外轮廓和内轮廓),因为我需要用这些数据进行进一步处理。
这实际上是对该问题的跟进:find archery target in image of different perspectives
由于这是一个更具体的问题,我创建了一个新问题。我是新来的
对Miki的回答的跟进。 其中一个结果如下: Contour of blue circle and fitting ellipse 二值图像中的轮廓和原始图像中产生的椭圆是不同的。
我仍然想解决这个问题。我正在考虑沿着二进制图像的轮廓并且在轮廓被破坏的任何地方的算法,算法继续使用最后已知的半径,直到找到轮廓的下一个像素。有这样的算法吗?或者也许是一种在特定点拉伸拟合椭圆直到轮廓的所有部分都被覆盖的方法?
答案 0 :(得分:0)
您可以查看Circle Hough Transform算法以查找红色,绿色和蓝色通道中的所有圆形对象,然后匹配它们。
您可以找到实施here或使用OpenCV realization。
答案 1 :(得分:0)
直接找到该图像中的省略号可能非常棘手。但是,您可以查看here以获取一些信息和对代码的引用。
在这种情况下,分割3种颜色要容易得多:蓝色,红色和黄色,找到外部轮廓,并且适合他们是一个椭圆。
所以,在这个输入图像上:
因此,您首先将图像转换为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);