使用 GoCV 检测黄色小圆圈

发布于 2025-01-17 02:09:51 字数 6350 浏览 0 评论 0原文

我正在尝试检测带有各种颜色的复选标记的圆圈。我想要检测的是带有白色复选标记的黄色,以及未来带有 x 标记的红色圆圈。 一个警告一个正常的很少有警告,很少正常lots of Standby Few Normal

到目前为止我一直在尝试的是这些代码以下。这一个使用霍夫圆方法。

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. one warning one normalfew warning few normallots of standby few normal

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.
bigger circle detection

But still no luck when I try with smaller circle.
smaller circle detection

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.
circle with colour masking

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

哭了丶谁疼 2025-01-24 02:09:51

所以我所做的是安装另一个由 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文