猿问

OpenCV 相当于 np.where()

例如,当使用gocv包时,可以执行图像内模式的模板匹配。该包还提供MinMaxLoc函数来检索矩阵内最小值和最大值的位置。

然而,在下面的 python 示例中,作者使用numpy.Where对矩阵进行阈值处理并获取多个最大值的位置。python zip函数用于将值粘合在一起,因此它们就像一个切片[][2]int,内部切片是找到的匹配项的 xs 和 ys。

该语法loc[::-1] 反转数组。

中的星号运算符zip(*loc..)用于解压提供给 zip 的切片。

import cv2 as cv

import numpy as np

from matplotlib import pyplot as plt


img_rgb = cv.imread('mario.png')

img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY)

template = cv.imread('mario_coin.png',0)

w, h = template.shape[::-1]

res = cv.matchTemplate(img_gray,template,cv.TM_CCOEFF_NORMED)

threshold = 0.8

loc = np.where( res >= threshold)


for pt in zip(*loc[::-1]):

    cv.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)

cv.imwrite('res.png',img_rgb)

如何np.where在 Go 中实现相同的算法来获取应用阈值后的多个位置?


慕沐林林
浏览 187回答 2
2回答

翻翻过去那场雪

OpenCV 有一个与 内置(半)等效的函数np.where(),即findNonZero()。正如名称所暗示的,它会查找图像中的非零元素,这就是np.where()使用单个参数调用时的作用,如numpy 文档所述。这在 golang 绑定中也可用。来自gocvFindNonZero 的文档:func FindNonZero(src Mat, idx *Mat)FindNonZero 返回非零像素位置的列表。注意:np.where()按数组顺序返回索引,即 (row, col) 或 (i, j),这与典型的图像索引 (x, y) 相反。这就是为什么locPython 中是相反的。使用时findNonZero()你不需要这样做,因为 OpenCV 总是使用 (x, y) 来表示点。

慕哥6287543

对于任何遇到这个问题的人,我希望有一个完整的例子,让你不用花几天时间把头撞在墙上,一遍又一遍地阅读相同的谷歌结果,直到有东西点击。package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "image"&nbsp; &nbsp; "image/color"&nbsp; &nbsp; "os"&nbsp; &nbsp; "gocv.io/x/gocv")func OpenImage(path string) (image.Image, error) {&nbsp; &nbsp; f, err := os.Open(path)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return nil, err&nbsp; &nbsp; }&nbsp; &nbsp; defer f.Close()&nbsp; &nbsp; img, _, err := image.Decode(f)&nbsp; &nbsp; return img, err}func main() {&nbsp; &nbsp; src := gocv.IMRead("haystack.png", gocv.IMReadGrayScale)&nbsp; &nbsp; tgt := gocv.IMRead("needle.png", gocv.IMReadGrayScale)&nbsp; &nbsp; if src.Empty() {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("failed to read image")&nbsp; &nbsp; &nbsp; &nbsp; os.Exit(1)&nbsp; &nbsp; }&nbsp; &nbsp; if tgt.Empty() {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("failed to read image")&nbsp; &nbsp; &nbsp; &nbsp; os.Exit(1)&nbsp; &nbsp; }&nbsp; &nbsp; // Get image size&nbsp; &nbsp; tgtImg, _ := tgt.ToImage()&nbsp; &nbsp; iX, iY := tgtImg.Bounds().Size().X, tgtImg.Bounds().Size().Y&nbsp; &nbsp; // Perform a match template operation&nbsp; &nbsp; res := gocv.NewMat()&nbsp; &nbsp; gocv.MatchTemplate(src, tgt, &res, gocv.TmSqdiffNormed, gocv.NewMat())&nbsp; &nbsp; // Set a thresh hold. Using the `gocv.TmSqdiffNormed` confidence levels are&nbsp; &nbsp; // reversed. Meaning the lowest value is actually the greatest confidence.&nbsp; &nbsp; // So here I perform an Inverse Binary Threshold setting all values&nbsp; &nbsp; // above 0.16 to 1.&nbsp; &nbsp; thresh := gocv.NewMat()&nbsp; &nbsp; gocv.Threshold(res, &thresh, 0.16, 1.0, gocv.ThresholdBinaryInv)&nbsp; &nbsp; // Filter out all the non-zero values.&nbsp; &nbsp; gocv.FindNonZero(thresh, &res)&nbsp; &nbsp; // FindNonZero returns a list or vector of locations in the form of a gocv.Mat when using gocv.&nbsp; &nbsp; // There may be a better way to do this, but I iterate through each found location getting the int vector in value&nbsp; &nbsp; // at each row. I have to convert the returned int32 values into ints. Then draw a rectangle around each point.&nbsp; &nbsp; //&nbsp; &nbsp; // The result of get res.GetVeciAt(i, 0) is just a slice of x, y integers so each value can be accessed by&nbsp; &nbsp; // using slice/array syntax.&nbsp; &nbsp; for i := 0; i < res.Rows(); i++ {&nbsp; &nbsp; &nbsp; &nbsp; x, y := res.GetVeciAt(i, 0)[0], res.GetVeciAt(i, 0)[1]&nbsp; &nbsp; &nbsp; &nbsp; xi, yi := int(x), int(y)&nbsp; &nbsp; &nbsp; &nbsp; gocv.Rectangle(&src, image.Rect(xi, yi, xi+iX, yi+iY), color.RGBA{0, 0, 0, 1}, 2)&nbsp; &nbsp; }&nbsp; &nbsp; w := gocv.NewWindow("Test")&nbsp; &nbsp; w.IMShow(src)&nbsp; &nbsp; if w.WaitKey(0) > 1 {&nbsp; &nbsp; &nbsp; &nbsp; os.Exit(0)&nbsp; &nbsp; }}
随时随地看视频慕课网APP

相关分类

Go
我要回答