【问题标题】:OpenCV equivalent of np.where()OpenCV 等效于 np.where()
【发布时间】:2020-03-04 21:02:24
【问题描述】:

当使用gocv 包时,例如,可以对图像中的图案执行template matching。该包还提供了MinMaxLoc 函数来检索矩阵中的最小值和最大值的位置。

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

语法loc[::-1]reverses数组。

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

https://docs.opencv.org/master/d4/dc6/tutorial_py_template_matching.html

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)

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

【问题讨论】:

    标签: opencv go matrix computer-vision gocv


    【解决方案1】:

    OpenCV 有一个内置的(半)等价于np.where() 的函数,即findNonZero()。顾名思义,它会在图像中找到非零元素,这就是 np.where() 在使用单个参数调用时所做的事情,如 the numpy docs 状态。

    这在 golang 绑定中也可用。来自gocv docs on FindNonZero

    func FindNonZero(src Mat, idx *Mat)
    

    FindNonZero 返回非零像素的位置列表。

    更多详情请见:https://docs.opencv.org/master/d2/de8/group__core__array.html#gaed7df59a3539b4cc0fe5c9c8d7586190

    注意:np.where() 按数组顺序返回索引,即 (row, col) 或 (i, j),这与典型的图像索引 (x, y) 相反。这就是为什么 loc 在 Python 中被反转的原因。当使用findNonZero() 时,您不需要这样做,因为 OpenCV 总是使用 (x, y) 作为点。

    【讨论】:

    • 你能解释一下这个算法使用 numpy 版本优于 opencv 版本的优势吗?如果有的话!我不清楚为什么这两个存在......
    • @mh-cbon 人们都可以使用;你会看到很多 numpy 函数,因为 OpenCV 在 Python 中使用 numpy 来表示矩阵,而不是原生的 cv::Mat(这有很多很好的理由),这意味着你可以直接在图像上使用 numpy 函数——很多人比 OpenCV 更了解 numpy。没有普遍的理由偏爱它(在某些平台上可能会快一点,如果您愿意,可以测试时间)。
    • findNonZero 输出格式有些不清楚。使用 c++ 库,人们似乎在做nonZeroCoordinates.at<Point>(i).x 。但是使用 gocv 我找不到等效的 Point 方法。同时,findNonZero 返回一个垫子类型cv32sc2,有 9 行、1 列、2 个通道。我还没有找到如何将这些值转换为位置。我已经阅读了stackoverflow.com/questions/19242662/… 并了解了第二种方法。但我想坚持方法 1,并尝试利用 findNonZero 返回矩阵。你能再帮忙吗?
    • 我的意思是,我不清楚 findNonZero 的格式输出,特别是它可以返回多少种不同的格式,以及如何处理它们。我猜……
    • 另外,如果我要从通道 0 获取 xs,从通道 1 获取 ys,因为通道长度 == 2,我发现很多相似的值相差 1 个像素,我该如何将其展平?这些问题不在主题范围内吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-25
    • 2020-10-08
    相关资源
    最近更新 更多