使用 GoCV 检测黄色小圆圈
我正在尝试检测带有各种颜色的复选标记的圆圈。我想要检测的是带有白色复选标记的黄色,以及未来带有 x 标记的红色圆圈。
到目前为止我一直在尝试的是这些代码以下。这一个使用霍夫圆方法。
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()
// 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
}
}
}
这是结果。上面的代码只能检测到一个红色圆圈(应该是两个)和一个黄色圆圈。
我一直在尝试转换用 python 编写的轮廓检测,结果却陷入了令人困惑的 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
所以我所做的是安装另一个由 vcaesar 称为 gcv 的库。有一个名为 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.