因此,我使用OpenCV (在Go with OpenCV中)尝试从一个木板游戏中提取碎片。最初,我在处理这个问题时取得了一定的成功,手动找到了每个球员的HSV值、颜色和棋盘位置。我成功地做到了这一点,并对每一件作品及其在董事会中的位置进行了规划。缺点是,如果使用不同的板--“查找”所有正确的HSV值,则需要相当严重的人与人之间的交互。I asked here建议从忽略颜色开始,找出所有的片段,然后使用颜色聚类算法来确定它是哪一个播放器。我可能也得为这些职位做点什么,但那是第二阶段。
所以现在我试着把所有的片段都提取出来,不管颜色。
我一开始试着使用NewSimpleBlobDetectorWithParams --尽管没有取得什么进展,但它似乎在错误的否定/阳性方面挣扎了很多。
我尝试了HoughCirclesWithParams,但这似乎非常依赖于参数,而且在实际检测到的部分中,我没有取得多大进展。目前我正在使用FindContours,这似乎给了我一些合理的准确性。让我们看看这些照片。
原始图像如下:
我已经建立了一个控制的“仪表板”,似乎最“有用”的东西是侵蚀、膨胀和门槛。
我当前的设置是一个负载的trackerbars/滑块来调整值,然后
gocv.CvtColor(clone, &clone, gocv.ColorRGBToGray)
erodeKernel := gocv.GetStructuringElement(gocv.MorphRect, image.Pt(trackers.erosionValue, trackers.erosionValue))
gocv.Erode(clone, &clone, erodeKernel)
dilateKernel := gocv.GetStructuringElement(gocv.MorphRect, image.Pt(trackers.dilateValue, trackers.dilateValue))
gocv.Dilate(clone, &clone, dilateKernel)
gocv.Threshold(clone, &clone, float32(trackers.thresTruncValue), 255, gocv.ThresholdTrunc)
gocv.Threshold(clone, &clone, float32(trackers.threshBinaryValue), 255, gocv.ThresholdBinary)
cannies := gocv.NewMat()
gocv.Canny(clone, &cannies, float32(trackers.cannyMin), float32(trackers.cannyMax))
cnts := gocv.FindContours(cannies, gocv.RetrievalTree, gocv.ChainApproxSimple)紧接着是
for i := 0; i < cnts.Size(); i++ {
cnt := cnts.At(i)
if len(cnt.ToPoints()) < 5 {
continue
}
rect := gocv.FitEllipse(cnt)
gocv.Circle(&colorImage, image.Pt(rect.Center.X, rect.Center.Y), (rect.Height + rect.Width)/4, cntColor, 3)
if gocv.ContourArea(cnt) < gocv.ArcLength(cnt, false) {
continue
}
gocv.Rectangle(&colorImage, rect.BoundingRect, rectColor, 2)
psVector := gocv.NewPointsVector()
psVector.Append(cnt)
gocv.DrawContours(&clone, psVector, 0, rectColor, 3)
if rect.Center.X == (rect.BoundingRect.Max.X + rect.BoundingRect.Min.X) / 2 && rect.Center.Y == (rect.BoundingRect.Min.Y + rect.BoundingRect.Max.Y) / 2 {
//Does the circle fit inside the square?
if float64(rect.Width * rect.Height) > math.Pi * math.Pow(float64((rect.Height+rect.Width)/4), 2) {
gocv.Circle(&colorImage, image.Pt(rect.Center.X, rect.Center.Y), 2, matchColor, 3)
pieces = append(pieces, image.Pt(rect.Center.X, rect.Center.Y))
}
}
}

这个想法是,如果轮廓有5个点,你就可以找到包围矩形,如果轮廓是封闭的,在轮廓中心画一个圆圈,如果它适合于边界矩形,它们共享相同的中心,可能是一个弹奏片。注意--我想出了这个原则,它是基于观察圆圈和包围矩形的位置,当它们匹配起来的时候,它看起来更像是一个弹奏曲。

所以我正在取得一些很好的进展。然而,我的问题是帮助挖掘出其他颜色的片段,也许更“有力”地挖出白色的部分。我觉得我没有足够的工具可供我支配,好像我增加了一件事,我不得不减少另一件事,而且由于某种原因,我觉得在一块板上找到30轮chequers应该是相当健壮的。当我调整值寻找栗色碎片时,我可以得到其中的一些。

但是,正如你所看到的,当你玩门槛/侵蚀/膨胀时,这种差异并不能很好地找到它们。

编辑:
我加入了hough循环算法,以显示它经常会碰到假负片--在这种情况下,它得到了1。
gocv.HoughCirclesWithParams(
clone,
&circles,
gocv.HoughGradient,
1, // dp
15, // minDist
75, // param1
20, // param2
20, // minRadius
45, // maxRadius
)
blue := color.RGBA{0, 0, 255, 0}
for i := 0; i < circles.Cols(); i++ {
v := circles.GetVecfAt(0, i)
// if circles are found
if len(v) > 2 {
x := int(v[0])
y := int(v[1])
r := int(v[2])
gocv.Circle(&colorImage, image.Pt(x, y), r, blue, 2)
}
}

这是我用的门槛。

所以我意识到我在这里说了很多。我正在寻找一些帮助,以发现在董事会上的所有播放部分。我是在gocv中这样做的,但是如果有人有一个很好的引用或其他东西,我可以使用python /转换python代码。
没有任何修正的原始图像就在这里。正如我所说的,我的目标是自动检测板上的30块,然后我可以使用聚类算法来确定它们属于哪一组(我认为.)我想用最少的人的交互,拖动滑块,因为这不是一个有趣的/良好的用户体验.
我的想法

发布于 2022-09-20 09:22:15
这并不完全是你的问题的答案,但如果你用目标检测来代替,这就容易多了。在我的教程中,我也找到了不同的对象。在这种情况下,我将有2个或3个类别:光片,暗片,可能还有另一个空空间类。
我通常使用OpenCV和Darknet/YOLO来解决这些问题。我的youtube频道上有很多教程。这里有一个简单的方法来检测一些形状:https://www.youtube.com/watch?v=yOJIRArZeig,这里是另一个显示用于解决Sudoku:https://www.youtube.com/watch?v=BUG7HlhuArw的OpenCV和Darknet/YOLO的
你的案子会和上一个类似。您将得到检测到的对象向量,其中包含图像或视频帧中每个对象的边界框坐标。如果有兴趣,这是我推荐开始的教程视频:https://www.youtube.com/watch?v=pJ2iyf_E9PM
https://stackoverflow.com/questions/73773468
复制相似问题