- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
前段时间我问a question about square detection和 karlphillip得出了一个不错的结果。
现在我想更进一步,找到边缘不完全可见的正方形。看看这个例子:
有什么想法吗?我正在使用 karlphillips 代码:
void find_squares(Mat& image, vector<vector<Point> >& squares)
{
// blur will enhance edge detection
Mat blurred(image);
medianBlur(image, blurred, 9);
Mat gray0(blurred.size(), CV_8U), gray;
vector<vector<Point> > contours;
// find squares in every color plane of the image
for (int c = 0; c < 3; c++)
{
int ch[] = {c, 0};
mixChannels(&blurred, 1, &gray0, 1, ch, 1);
// try several threshold levels
const int threshold_level = 2;
for (int l = 0; l < threshold_level; l++)
{
// Use Canny instead of zero threshold level!
// Canny helps to catch squares with gradient shading
if (l == 0)
{
Canny(gray0, gray, 10, 20, 3); //
// Dilate helps to remove potential holes between edge segments
dilate(gray, gray, Mat(), Point(-1,-1));
}
else
{
gray = gray0 >= (l+1) * 255 / threshold_level;
}
// Find contours and store them in a list
findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
// Test contours
vector<Point> approx;
for (size_t i = 0; i < contours.size(); i++)
{
// approximate contour with accuracy proportional
// to the contour perimeter
approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);
// Note: absolute value of an area is used because
// area may be positive or negative - in accordance with the
// contour orientation
if (approx.size() == 4 &&
fabs(contourArea(Mat(approx))) > 1000 &&
isContourConvex(Mat(approx)))
{
double maxCosine = 0;
for (int j = 2; j < 5; j++)
{
double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
maxCosine = MAX(maxCosine, cosine);
}
if (maxCosine < 0.3)
squares.push_back(approx);
}
}
}
}
}
最佳答案
您可以尝试使用 HoughLines检测正方形的四个边。接下来,定位四个生成的线交叉点以检测角点。 Hough transform对噪声和遮挡相当稳健,因此在这里可能很有用。另外,here是一个交互式演示,展示了霍夫变换是如何工作的(我认为它至少很酷:)。 Here是我以前的答案之一,它检测到显示大部分相同数学的激光交叉中心(除了它只找到一个角)。
每边可能会有多条线,但定位交叉点应该有助于确定内点与异常点。找到候选角后,您还可以按面积或多边形的“方形”程度过滤这些候选角。
编辑:所有这些带有代码和图像的答案让我觉得我的答案有点缺乏:) 所以,这里是你如何做到这一点的实现:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <vector>
using namespace cv;
using namespace std;
Point2f computeIntersect(Vec2f line1, Vec2f line2);
vector<Point2f> lineToPointPair(Vec2f line);
bool acceptLinePair(Vec2f line1, Vec2f line2, float minTheta);
int main(int argc, char* argv[])
{
Mat occludedSquare = imread("Square.jpg");
resize(occludedSquare, occludedSquare, Size(0, 0), 0.25, 0.25);
Mat occludedSquare8u;
cvtColor(occludedSquare, occludedSquare8u, CV_BGR2GRAY);
Mat thresh;
threshold(occludedSquare8u, thresh, 200.0, 255.0, THRESH_BINARY);
GaussianBlur(thresh, thresh, Size(7, 7), 2.0, 2.0);
Mat edges;
Canny(thresh, edges, 66.0, 133.0, 3);
vector<Vec2f> lines;
HoughLines( edges, lines, 1, CV_PI/180, 50, 0, 0 );
cout << "Detected " << lines.size() << " lines." << endl;
// compute the intersection from the lines detected...
vector<Point2f> intersections;
for( size_t i = 0; i < lines.size(); i++ )
{
for(size_t j = 0; j < lines.size(); j++)
{
Vec2f line1 = lines[i];
Vec2f line2 = lines[j];
if(acceptLinePair(line1, line2, CV_PI / 32))
{
Point2f intersection = computeIntersect(line1, line2);
intersections.push_back(intersection);
}
}
}
if(intersections.size() > 0)
{
vector<Point2f>::iterator i;
for(i = intersections.begin(); i != intersections.end(); ++i)
{
cout << "Intersection is " << i->x << ", " << i->y << endl;
circle(occludedSquare, *i, 1, Scalar(0, 255, 0), 3);
}
}
imshow("intersect", occludedSquare);
waitKey();
return 0;
}
bool acceptLinePair(Vec2f line1, Vec2f line2, float minTheta)
{
float theta1 = line1[1], theta2 = line2[1];
if(theta1 < minTheta)
{
theta1 += CV_PI; // dealing with 0 and 180 ambiguities...
}
if(theta2 < minTheta)
{
theta2 += CV_PI; // dealing with 0 and 180 ambiguities...
}
return abs(theta1 - theta2) > minTheta;
}
// the long nasty wikipedia line-intersection equation...bleh...
Point2f computeIntersect(Vec2f line1, Vec2f line2)
{
vector<Point2f> p1 = lineToPointPair(line1);
vector<Point2f> p2 = lineToPointPair(line2);
float denom = (p1[0].x - p1[1].x)*(p2[0].y - p2[1].y) - (p1[0].y - p1[1].y)*(p2[0].x - p2[1].x);
Point2f intersect(((p1[0].x*p1[1].y - p1[0].y*p1[1].x)*(p2[0].x - p2[1].x) -
(p1[0].x - p1[1].x)*(p2[0].x*p2[1].y - p2[0].y*p2[1].x)) / denom,
((p1[0].x*p1[1].y - p1[0].y*p1[1].x)*(p2[0].y - p2[1].y) -
(p1[0].y - p1[1].y)*(p2[0].x*p2[1].y - p2[0].y*p2[1].x)) / denom);
return intersect;
}
vector<Point2f> lineToPointPair(Vec2f line)
{
vector<Point2f> points;
float r = line[0], t = line[1];
double cos_t = cos(t), sin_t = sin(t);
double x0 = r*cos_t, y0 = r*sin_t;
double alpha = 1000;
points.push_back(Point2f(x0 + alpha*(-sin_t), y0 + alpha*cos_t));
points.push_back(Point2f(x0 - alpha*(-sin_t), y0 - alpha*cos_t));
return points;
}
注意:我调整图像大小的主要原因是我可以在屏幕上看到它,并加快处理速度。
这使用 Canny 边缘检测来帮助大大减少阈值处理后检测到的行数。
然后使用霍夫变换来检测正方形的边。
最后,我们计算所有线对的交点。
希望有帮助!
关于c++ - OpenCV C++/Obj-C : Advanced square detection,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10533233/
今天,我在 Windows 10 的“程序和功能”列表中看到了 2 个不同版本的 ARC,因此我选择卸载旧版本,因为我需要一些空间。在卸载结束时,它们都消失了! 所以,我从 https://insta
我刚买了一台更强大的电脑,安装了 composer 并想继续我的项目,但是当我使用 gii 时,它给了我这个错误。 我该如何解决?为什么我得到它?谢谢你。 最佳答案 解决了。自 2.0.13 起,类名
一、介绍 这是我的《Advanced .Net Debugging》这个系列的第十篇文章。这篇文章的内容是原书的第三部分的【高级主题】的第八章【事后调试】。前面几篇文章,我们介绍了很多工具,可以
一、介绍 这是我的《 Advanced .Net Debugging》这个系列的第八篇文章。这篇文章的内容是原书的第二部分的【调试实战】的第六章【同步】。我们经常写一些多线程的应用程序,写的多
一、介绍 这是我的《 Advanced .Net Debugging》这个系列的第九篇文章。这篇文章的内容是原书的第二部分的【调试实战】的第七章【互用性】。互用性包含两个方面,第一个方面就是托
一、简介 这是我的《Advanced .Net Debugging》这个系列的第七篇文章。这篇文章的内容是原书的第二部分的【调试实战】的第五章,这一章主要讲的是从根本上认识托管堆和垃圾回收。软件
一、简介 这是我的《 Advanced .Net Debugging》这个系列的第六篇文章。这篇文章的内容是原书的第二部分的【调试实战】的第四章。这章主要讲的是程序集加载器,比如:CLR 加载
一、简介 我曾看到过许多开发人员使用错误的工具来分析问题,更有甚者,有些人连任何工具都没有使用。他们采取的分析方法通常包括:输出更多的调试信息,或者做一
一、简介 我曾看到过许多开发人员使用错误的工具来分析问题,更有甚者,有些人连任何工具都没有使用。他们采取的分析方法通常包括:输出更多的调试信息,或者做一
一、简介 我曾看到过许多开发人员使用错误的工具来分析问题,更有甚者,有些人连任何工具都没有使用。他们采取的分析方法通常包括:输出更多的调试信息,或者做一
我是 yii2 的新手,当我使用 从存档中提取 yii2 高级内容时《基本应用模板》、《带有高级应用模板的Yii 2》当我在服务器上上传时,它显示空白页面。 我检查了 yii2 basic 它工作正常
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 6 年前。 Improve this ques
如果我遗漏了任何重要的细节,我想提前道歉。 我正在尝试执行升级,在安装新版本之前应删除以前版本的软件(和所有组件)。 我会尽量避免让您厌烦细节,并说如果您进行“典型”安装,一切都会按计划进行。如果您选
您好,我正在尝试创建一个存储整数或字符串元素的通用列表迭代器。我正在尝试测试它调用 IteratorG advance(IteratorG it, int n) 函数的情况,该函数采用在列表 it 中
我想知道是否有任何可能的方法,使 MySQL 查询可以动态搜索 WHERE 子句中的任何内容。 例如,如果查询是 Select * from table where item = 'Dell Opti
我正在使用 PayPal Advanced,并使用用户定义的字段 USER1 - USER10 发送一些交易数据,这将帮助我在通过 Silent Post 请求返回时识别它。有谁知道这些 USERx
这个问题在这里已经有了答案: How to use "distanceTo", "advancedBy" to handle String in Xcode7 beta6 (2 个答案) 关闭 7
请告诉我如何提前获得 transactionHash? // I have these tx opts: var txOpts = { "to":"0x345cA3e014Aaf5dcA48805
我正在尝试使用 Eloquent 创建类似的东西。但是,我在使用 or 子句时遇到了麻烦。 SELECT * FROM table WHERE column1 = 1 AND column2 = 2
我似乎无法理解以下 example in Advanced R . x for (i in 1:5) { y[[i]] tracemem[0x7f80c5c3de20 -> 0x7f80c4
我是一名优秀的程序员,十分优秀!