我正在寻找一种方法来获取从Canny边缘检测中提取的薄轮廓的终点。我想知道这是可能的一些内置方式。我计划在轮廓中走动以找到彼此距离最大的两个点(仅沿着轮廓移动),但如果已经存在一种方式则会更容易。我看到cvarcLength存在以获得轮廓的周长,因此可能有一种内置的方法来实现这一点。是否以这样的方式排列轮廓内的点,以便可以知道关于终点的一些信息?还有其他想法吗?非常感谢!
答案 0 :(得分:1)
我一直在寻找相同的功能,我看到HoughLinesP有端点,因为线条不是轮廓线。我正在使用findContours,所以我发现在下面的轮廓中订购点是有帮助的,而不是将第一个和最后一个点作为起点和终点。
struct contoursCmpY {
bool operator()(const Point &a,const Point &b) const {
if (a.y == b.y)
return a.x < b.x;
return a.y < b.y;
}
} contoursCmpY_;
vector<Point> cont;
cont.push_back(Point(194,72));
cont.push_back(Point(253,14));
cont.push_back(Point(293,76));
cont.push_back(Point(245,125));
std::sort(cont.begin(),cont.end(), contoursCmpY_);
int size = cont.size();
printf("start Point x=%d,y=%d end Point x=%d,y=%d", cont[0].x, cont[0].y, cont[size].x, cont[size].y);
答案 1 :(得分:0)
正如您所说,您始终可以单步执行轮廓点。
以下内容找到了两个点ptLeft
和ptRight
,它们与x的分隔最大,但可以根据需要进行修改。
CvPoint ptLeft = cvPoint(image->width, image->height);
CvPoint ptRight = cvPoint(0, 0);
CvSlice slice = cvSlice(0, CV_WHOLE_SEQ_END_INDEX);
CvSeqReader reader;
cvStartReadSeq(contour, &reader, 0);
cvSetSeqReaderPos(&reader, slice.start_index);
int count = cvSliceLength(slice, contour);
for(int i = 0; i < count; i++)
{
reader.prev_elem = reader.ptr;
CV_NEXT_SEQ_ELEM(contour->elem_size, reader);
CvPoint* pt = (CvPoint*)reader.ptr;
if( pt->x < ptLeft.x )
ptLeft = *pt;
if( pt->x > ptRight.x )
ptRight = *pt;
}
答案 2 :(得分:0)
基于邻居距离检查的解决方案对我来说不起作用(Python + opencv 3.0.0-beta),因为我得到的所有轮廓似乎都折叠在自己身上。什么看起来像&#34;打开&#34;乍一看图像上的轮廓实际上是关闭的&#34;轮廓坍塌了。
所以我不得不求助于&#34; u-turns&#34;在每个轮廓的序列中,Python中的一个例子:
import numpy as np
def draw_closing_lines(img, contours):
for cont in contours:
v1 = (np.roll(cont, -2, axis=0) - cont)
v2 = (np.roll(cont, 2, axis=0) - cont)
dotprod = np.sum(v1 * v2, axis=2)
norm1 = np.sqrt(np.sum(v1 ** 2, axis=2))
norm2 = np.sqrt(np.sum(v2 ** 2, axis=2))
cosinus = (dotprod / norm1) / norm2
indexes = np.where(0.95 < cosinus)[0]
if len(indexes) == 1:
# only one u-turn found, mark in yellow
cv2.circle(img, tuple(cont[indexes[0], 0]), 3, (0, 255, 255))
elif len(indexes) == 2:
# two u-turns found, draw the closing line
cv2.line(img, tuple(tuple(cont[indexes[0], 0])), tuple(cont[indexes[1], 0]), (0, 0, 255))
else:
# too many u-turns, mark in red
for i in indexes:
cv2.circle(img, tuple(cont[i, 0]), 3, (0, 0, 255))
不能完全抵御污染尖点并且非常耗时,但这是一个开始。我自然会对其他想法感兴趣:)