英文:
Yellow Small Circle Detection Using GoCV
问题
我正在尝试检测带有各种颜色的带有勾号的圆圈。我想要检测的是黄色的圆圈和白色的勾号,将来还想要检测带有红色圆圈和X标记的情况。
我尝试了以下这些代码。这个代码使用了Hough圆检测方法。
package main
import (
"fmt"
"image"
"image/color"
"os"
"gocv.io/x/gocv"
)
func DetectCircles() {
if len(os.Args) < 2 {
fmt.Println("How to run:\n\tfind-circles [imgfile]")
return
}
filename := os.Args[1]
grey_window := gocv.NewWindow("grey window")
grey_window.MoveWindow(600, 0)
window := gocv.NewWindow("detected circles")
defer grey_window.Close()
defer window.Close()
original_img := gocv.IMRead(filename, gocv.IMReadColor)
defer original_img.Close()
img := gocv.NewMat()
defer img.Close()
gocv.CvtColor(original_img, &img, gocv.ColorBGRToGray)
gocv.MedianBlur(img, &img, 5)
circles := gocv.NewMat()
defer circles.Close()
gocv.HoughCirclesWithParams(
img,
&circles,
gocv.HoughGradient,
1, // dp
// float64(img.Rows()/8), // minDist
26,
200, // param1
48, // param2
0, // minRadius
0, // maxRadius
)
green := color.RGBA{0, 255, 0, 0}
red := color.RGBA{255, 0, 0, 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(&original_img, image.Pt(x, y), r, green, 2)
gocv.Circle(&original_img, image.Pt(x, y), 2, red, 3)
}
}
for {
window.IMShow(original_img)
if window.WaitKey(10) >= 0 {
break
}
}
}
通过一些调整,我设法检测到了一些较大的圆圈,如下所示:
但是当我尝试检测较小的圆圈时,没有成功。
以下是我编写的用于隔离颜色的代码。我所做的是从一定的HSV范围内添加一些颜色掩码。
package main
import (
"fmt"
"image"
"image/color"
"os"
"gocv.io/x/gocv"
)
func DetectCircles2() {
if len(os.Args) < 2 {
fmt.Println("How to run:\n\tgo run . [imgfile]")
return
}
filename := os.Args[1]
window := gocv.NewWindow("detected colors")
window2 := gocv.NewWindow("end result")
window3 := gocv.NewWindow("lower bound")
window4 := gocv.NewWindow("upper bound")
window2.MoveWindow(600, 0)
window3.MoveWindow(0, 600)
window4.MoveWindow(600, 600)
defer window.Close()
defer window2.Close()
defer window3.Close()
defer window4.Close()
img := gocv.IMRead(filename, gocv.IMReadColor)
defer img.Close()
original_image := img.Clone()
defer original_image.Close()
gocv.MedianBlur(img, &img, 3)
hsv_img := gocv.NewMat()
defer hsv_img.Close()
gocv.CvtColor(img, &hsv_img, gocv.ColorBGRToHSV)
img_rows, img_cols := hsv_img.Rows(), hsv_img.Cols()
lb1 := gocv.NewMatWithSizeFromScalar(gocv.NewScalar(20.0, 50.0, 50.0, 0.0), img_rows, img_cols, gocv.MatTypeCV8UC3)
ub1 := gocv.NewMatWithSizeFromScalar(gocv.NewScalar(40.0, 255.0, 255.0, 0.0), img_rows, img_cols, gocv.MatTypeCV8UC3)
lb2 := gocv.NewMatWithSizeFromScalar(gocv.NewScalar(155.0, 100.0, 100.0, 0.0), img_rows, img_cols, gocv.MatTypeCV8UC3)
ub2 := gocv.NewMatWithSizeFromScalar(gocv.NewScalar(180.0, 255.0, 255.0, 0.0), img_rows, img_cols, gocv.MatTypeCV8UC3)
lower_bound := gocv.NewMat()
upper_bound := gocv.NewMat()
color_isolated_img := gocv.NewMat()
circles := gocv.NewMat()
defer lower_bound.Close()
defer upper_bound.Close()
defer color_isolated_img.Close()
defer circles.Close()
gocv.InRange(hsv_img, lb1, ub1, &lower_bound)
gocv.InRange(hsv_img, lb2, ub2, &upper_bound)
gocv.AddWeighted(lower_bound, 1.0, upper_bound, 1.0, 0.0, &color_isolated_img)
gocv.GaussianBlur(color_isolated_img, &color_isolated_img, image.Pt(9, 9), 2, 2, gocv.BorderDefault)
gocv.HoughCirclesWithParams(
color_isolated_img,
&circles,
gocv.HoughGradient,
1,
float64(color_isolated_img.Rows()/8),
100,
20,
0,
0,
)
green := color.RGBA{0, 255, 0, 0}
for i := 0; i < circles.Cols(); i++ {
v := circles.GetVecfAt(0, i)
fmt.Println(v)
if len(v) > 2 {
x := int(v[0])
y := int(v[1])
r := int(v[2])
gocv.Circle(&original_image, image.Pt(x, y), r, green, 2)
}
}
for {
window2.IMShow(original_image)
window3.IMShow(lower_bound)
window4.IMShow(upper_bound)
if window.WaitKey(10) >= 0 {
break
}
}
}
这是结果。上面的代码只能检测到一个红色圆圈(应该是两个)和一个黄色圆圈。
我一直在尝试将Python中的轮廓检测转换为GoCV,但遇到了令人困惑的GoCV API。我在希望GoCV和OpenCV社区能够帮助我正确检测小而多彩的圆圈。非常感谢您的建议。
英文:
I'm trying to detect circle with checkmark with variety of colours. What I want to detect is yellow with white checkmark, and in the future red circle with x mark.
What I've been trying so far are these codes below. This one using Hough Circles method.
package main
import (
"fmt"
"image"
"image/color"
"os"
"gocv.io/x/gocv"
)
func DetectCircles() {
if len(os.Args) < 2 {
fmt.Println("How to run:\n\tfind-circles [imgfile]")
return
}
filename := os.Args[1]
grey_window := gocv.NewWindow("grey window")
grey_window.MoveWindow(600, 0)
window := gocv.NewWindow("detected circles")
defer grey_window.Close()
defer window.Close()
original_img := gocv.IMRead(filename, gocv.IMReadColor)
defer original_img.Close()
img := gocv.NewMat()
defer img.Close()
gocv.CvtColor(original_img, &img, gocv.ColorBGRToGray)
gocv.MedianBlur(img, &img, 5)
circles := gocv.NewMat()
defer circles.Close()
gocv.HoughCirclesWithParams(
img,
&circles,
gocv.HoughGradient,
1, // dp
// float64(img.Rows()/8), // minDist
26,
200, // param1
48, // param2
0, // minRadius
0, // maxRadius
)
green := color.RGBA{0, 255, 0, 0}
red := color.RGBA{255, 0, 0, 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(&original_img, image.Pt(x, y), r, green, 2)
gocv.Circle(&original_img, image.Pt(x, y), 2, red, 3)
}
}
for {
window.IMShow(original_img)
if window.WaitKey(10) >= 0 {
break
}
}
}
With some adjustment, I manage to detect some bigger circles like these.
But still no luck when I try with smaller circle.
These are the codes I wrote to isolate the colour. What I did was adding some colour mask from and to certain HSV range.
package main
import (
"fmt"
"image"
"image/color"
"os"
"gocv.io/x/gocv"
)
func DetectCircles2() {
if len(os.Args) < 2 {
fmt.Println("How to run:\n\tgo run . [imgfile]")
return
}
filename := os.Args[1]
window := gocv.NewWindow("detected colors")
window2 := gocv.NewWindow("end result")
window3 := gocv.NewWindow("lower bound")
window4 := gocv.NewWindow("upper bound")
window2.MoveWindow(600, 0)
window3.MoveWindow(0, 600)
window4.MoveWindow(600, 600)
defer window.Close()
defer window2.Close()
defer window3.Close()
defer window4.Close()
img := gocv.IMRead(filename, gocv.IMReadColor)
defer img.Close()
original_image := img.Clone()
defer original_image.Close()
gocv.MedianBlur(img, &img, 3)
hsv_img := gocv.NewMat()
defer hsv_img.Close()
// yellow := gocv.NewScalar(0, 255, 255, 0)
// yellow_mat := gocv.NewMatFromScalar(yellow, gocv.MatTypeCV8UC3)
// gocv.CvtColor(yellow_mat, &yellow_mat, gocv.ColorBGRToHSV)
// hsv := gocv.Split(yellow_mat)
// fmt.Printf("H: %d S: %d V: %d\n", hsv[0].GetUCharAt(0, 0), hsv[1].GetUCharAt(0, 0), hsv[2].GetUCharAt(0, 0))
gocv.CvtColor(img, &hsv_img, gocv.ColorBGRToHSV)
img_rows, img_cols := hsv_img.Rows(), hsv_img.Cols()
// lb1 := gocv.NewMatWithSizeFromScalar(gocv.NewScalar(0.0, 208.0, 94.0, 0.0), img_rows, img_cols, gocv.MatTypeCV8UC3)
// ub1 := gocv.NewMatWithSizeFromScalar(gocv.NewScalar(179.0, 255.0, 255.0, 0.0), img_rows, img_cols, gocv.MatTypeCV8UC3)
lb1 := gocv.NewMatWithSizeFromScalar(gocv.NewScalar(20.0, 50.0, 50.0, 0.0), img_rows, img_cols, gocv.MatTypeCV8UC3)
ub1 := gocv.NewMatWithSizeFromScalar(gocv.NewScalar(40.0, 255.0, 255.0, 0.0), img_rows, img_cols, gocv.MatTypeCV8UC3)
lb2 := gocv.NewMatWithSizeFromScalar(gocv.NewScalar(155.0, 100.0, 100.0, 0.0), img_rows, img_cols, gocv.MatTypeCV8UC3)
ub2 := gocv.NewMatWithSizeFromScalar(gocv.NewScalar(180.0, 255.0, 255.0, 0.0), img_rows, img_cols, gocv.MatTypeCV8UC3)
lower_bound := gocv.NewMat()
upper_bound := gocv.NewMat()
color_isolated_img := gocv.NewMat()
circles := gocv.NewMat()
defer lower_bound.Close()
defer upper_bound.Close()
defer color_isolated_img.Close()
defer circles.Close()
gocv.InRange(hsv_img, lb1, ub1, &lower_bound)
gocv.InRange(hsv_img, lb2, ub2, &upper_bound)
gocv.AddWeighted(lower_bound, 1.0, upper_bound, 1.0, 0.0, &color_isolated_img)
gocv.GaussianBlur(color_isolated_img, &color_isolated_img, image.Pt(9, 9), 2, 2, gocv.BorderDefault)
gocv.HoughCirclesWithParams(
color_isolated_img,
&circles,
gocv.HoughGradient,
1,
float64(color_isolated_img.Rows()/8),
100,
20,
0,
0,
)
green := color.RGBA{0, 255, 0, 0}
for i := 0; i < circles.Cols(); i++ {
v := circles.GetVecfAt(0, i)
fmt.Println(v)
if len(v) > 2 {
x := int(v[0])
y := int(v[1])
r := int(v[2])
gocv.Circle(&original_image, image.Pt(x, y), r, green, 2)
}
}
for {
// window.IMShow(color_isolated_img)
window2.IMShow(original_image)
window3.IMShow(lower_bound)
window4.IMShow(upper_bound)
if window.WaitKey(10) >= 0 {
break
}
}
}
Here is the result. Code above only manage to detect one red circle (it's supposed to be two) and one yellow circle.
I've been trying to convert contour detection written in python only to stumble to confusing gocv API. I'm tagging gocv and opencv in hope these two communities would help me to properly detect small colourful circles. Any advice will be appreciated. Thank you very much.
答案1
得分: 0
所以我所做的是安装了一个名为gcv的库,由vcaesar开发。其中有一个名为FindAllImg的方法,我只需要提供两个图像,一个是源图像(在我的情况下是屏幕截图),另一个是需要在截图中搜索的模板图像。
英文:
So what I did was I installing another library that's called gcv by vcaesar. There was a method called FindAllImg and what I need just provide two image, one is the source image, in my case a screenshot, and the other is a template image that needed to be searched in the screenshot.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论