回答此问题可获得 20 贡献值,回答如果被采纳可获得 50 分。
<h2>问题</h2>
<p>我正在做一个项目,我需要得到哑铃形状的边界框。但是,我需要尽可能少的点,并且盒子需要适合所有角落的形状。下面是我做的一个图像测试:<a href="http://i.imgur.com/I455ocE.png" rel="nofollow">Blurry, cracked, dumbell shape</a></p>
<p>我不在乎形状的间隙,我只想把它清理干净,把边弄直,这样我就可以得到这样一个形状的轮廓:<a href="http://i.imgur.com/EEvDbie.png" rel="nofollow">Cleaned up</a></p>
<p>我一直在尝试<code>threshold()</code>它,用<code>findContours()</code>得到它的轮廓,然后用<code>approxPolyDP()</code>来简化轮廓最终的疯狂数量。所以,在摆弄了三天之后,我怎么能简单地得到:</p>
<ul>
<li>两个方框,指定哑铃的末端和中间的矩形,或</li>
<li>一个轮廓,所有角有十二个点</li>
</ul>
<p>第二个选择是首选的,因为这确实是我的最终目标:得到那些角落的分数。在</p>
<h2>有几点需要注意:</h2>
<ul>
<li>我正在使用OpenCV for Python</li>
<li>在输入图像中通常会有许多不同大小的形状</li>
<li>他们将只有水平或垂直定位。没有奇怪的27度角。。。在</li>
</ul>
<h2>我需要的是:</h2>
<p>我真的不需要别人为我写代码,我只需要一些方法或算法来完成这项工作,最好是一些简单的例子。在</p>
<h2>我的代码</h2>
<p>下面是我的代码,其中有一些我甚至不使用的函数,但我最终会使用它们:</p>
<pre><code>import cv2
import numpy as np
class traceImage():
def __init__(self, imageLocation):
self.threshNum = 127
self.im = cv2.imread(imageLocation)
self.imOrig = self.im
self.imGray = cv2.cvtColor(self.im, cv2.COLOR_BGR2GRAY)
self.ret, self.imThresh = cv2.threshold(self.imGray, self.threshNum, 255, 0)
self.contours, self.hierarchy = cv2.findContours(self.imThresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
def createGray(self):
self.imGray = cv2.cvtColor(self.im, cv2.COLOR_BGR2GRAY)
def adjustThresh(self, threshNum):
self.ret, self.imThresh = cv2.threshold(self.imGray, threshNum, 255, 0)
def getContours(self):
self.contours, self.hierarchy = cv2.findContours(self.imThresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
def approximatePoly(self, percent):
i=0
for shape in self.contours:
shape = cv2.approxPolyDP(shape, percent*cv2.arcLength(shape, True), True)
self.contours[i] = shape
i+=1
def drawContours(self, blobWidth, color=(255,255,255)):
cv2.drawContours(self.im, self.contours, -1, color, blobWidth)
def newWindow(self, name):
cv2.namedWindow(name)
def showImage(self, window):
cv2.imshow(window, self.im)
def display(self):
while True:
cv2.waitKey()
def displayUntil(self, key):
while True:
pressed = cv2.waitKey()
if pressed == key:
break
if __name__ == "__main__":
blobWidth = 30
ti = traceImage("dumbell.png")
ti.approximatePoly(0.01)
for thresh in range(127,256):
ti.adjustThresh(thresh)
ti.getContours()
ti.drawContours(blobWidth)
ti.showImage("Image")
ti.displayUntil(10)
ti.createGray()
ti.adjustThresh(127)
ti.getContours()
ti.approximatePoly(0.0099)
ti.drawContours(2, (0,255,0))
ti.showImage("Image")
ti.display()
</code></pre>
<h2>代码说明</h2>
<p>我知道我可能不会在这里做一些事情,但是嘿,我很自豪:)</p>
<p>所以,我们的想法是这些哑铃上经常会有洞和缝隙,所以我想如果我迭代127到255之间的所有阈值,把轮廓画到足够厚的图像上,绘制轮廓的厚度会填充任何足够小的洞,我可以使用新的,滴状图像获取边缘,然后将边缩小到大小。那是我的想法。一定有另一种更好的方式。。。在</p>
<h2>摘要</h2>
<p>我想得到12个点,每个角对应一个点。在</p>
<h2>编辑:</h2>
<p>在尝试了一些腐蚀和膨胀之后,似乎最好的选择是在某些点切割轮廓,然后在切片形状周围使用边界框来获得正确的方形角,然后进行一些计算,将这些长方体重新连接成一个形状。一个相当有趣的挑战。。。在</p>
<h2>编辑2:</h2>
<p>我发现了一些有用的东西!我做了我自己的直线检测系统,只检测水平线或垂直线,然后在检测到的直线/轮廓边缘上,程序绘制出一条延伸到整个图像的黑线,从而有效地在等高线的直线上对图像进行切片。一旦这样做了,它会得到切片盒的新轮廓,在碎片周围绘制边界框,然后使用膨胀来缩小间隙。到目前为止,它在大的形状上效果很好,但是当形状很小时,它往往会失去一点形状。在</p>