gpt4 book ai didi

c++ - 检测七边形对象不正确

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:45:29 25 4
gpt4 key购买 nike

我想检测一个七边形对象(箭头)。我使用 Opencv 进行简单的形状检测来检测七边形(7 个顶点)。使用代码,我能够检测到三角形、圆形、矩形,但不能检测到七边形对象(在图像中它是一个箭头)。这是我的代码

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>

using namespace cv;
using namespace std;

Mat src; Mat src_gray;

/**
* 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,255,255), CV_FILLED);
cv::putText(im, label, pt, fontface, scale, CV_RGB(0,0,0), thickness, 8);
}

int main()
{

cv::Mat src = cv::imread("shapes.png");
if (src.empty())
return -1;

// Convert to grayscale
cv::Mat gray;
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_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

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.02, true);

// Skip small or non-convex objects
if (std::fabs(cv::contourArea(contours[i])) < 100 || !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.1 && maxcos <= 0.3)
setLabel(dst, "RECT", contours[i]);
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]);
if (vtc ==7 && mincos >= 10.1 && maxcos <= -10.45)
setLabel(dst, "ARROW", 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);
cv::imshow("dst", dst);
cv::waitKey(0);
return 0;
}

这是输入图像 Input

这是输出 result

有什么帮助吗?

最佳答案

在您的代码中:

// Skip small or non-convex objects
if (std::fabs(cv::contourArea(contours[i])) < 100 || !cv::isContourConvex(approx))
continue;

取出!cv::isContourConvex(approx),这可能就是您拥有的七边形被忽略的原因,因为它们实际上是非凸的。

aprox.size() <= 6else if条件也可能过滤掉七边形。

关于检查箭头形状,因为底座是方形的,你可以尝试这样的东西:

 bool isRightCosin(double c){
// This covers cosin of both convex and none-convex right angles, since
// there is no way to distinguish them
return -0.1 <= c && c <= 0.1
}

bool isArrow(std::vector<cv::Point> & approx){
// It checks if the polygon is an heptagon and contains a square shaped
// sub-structure. Beware, some other shapes could pass the test:
//
// /\ /\ /\
// / \ ___/ \____ / \
// / \ | | / \
// /_ _\ | | / __ \
// | | |_________| / | | \
// |__| /___| |___\


int vtc = approx.size();
if (vtc!=7) {
return false;
}

// Get the cosines of all corners, with redundancy, to make the
// algorithm easier
std::vector<double> cosines;
for (int j = 0; j < vtc+5; j++){
cosines.push_back(angle(approx[(j+2)%vtc],
approx[j%vtc],
approx[(j+1)%vtc]));
}

for (int j = 0; j < vtc; j++){
if (isRightCosin(cosines[j]) && isRightCosin(cosines[j+1])
isRightCosin(cosines[j+2]) && isRightCosin(cosines[j+3]){
return true;
}
return false;
}

关于c++ - 检测七边形对象不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39634805/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com