OpenCV 中是否可以将局部曲率绘制为代表对象“指向性”的热图?

2024-04-11

给定一个可以检测并绘制轮廓的斑点阈值图像,在绘制轮廓时是否可以将局部曲率表示为热图?

即是否 (1) 可以确定开放 cv 轮廓上的局部曲率 (2) 将此曲率映射到热图颜色空间 (3) 将轮廓绘制为热图。

我的目标是测量对象的“尖度”,以便我可以绘制从尖头侧到相反的非尖头侧的矢量。对于我的物体,我碰巧知道尖的一面是顶部。

如果其他技术比曲率更能有效地表示“尖角”,请随时提出建议。


EDIT:修复了上一个版本的错误。

我使用轮廓上第 i 个点和第 (i + n) 个点处的梯度向量之间的角度作为分数来确定点的尖度。代码和结果如下。

import numpy as np
import cv2
import pylab as pl


def compute_pointness(I, n=5):
    # Compute gradients
    # GX = cv2.Sobel(I, cv2.CV_32F, 1, 0, ksize=5, scale=1)
    # GY = cv2.Sobel(I, cv2.CV_32F, 0, 1, ksize=5, scale=1)
    GX = cv2.Scharr(I, cv2.CV_32F, 1, 0, scale=1)
    GY = cv2.Scharr(I, cv2.CV_32F, 0, 1, scale=1)
    GX = GX + 0.0001  # Avoid div by zero

    # Threshold and invert image for finding contours
    _, I = cv2.threshold(I, 100, 255, cv2.THRESH_BINARY_INV)
    # Pass in copy of image because findContours apparently modifies input.
    C, H = cv2.findContours(I.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    heatmap = np.zeros_like(I, dtype=np.float)
    pointed_points = []
    for contour in C:
        contour = contour.squeeze()
        measure = []
        N = len(contour)
        for i in xrange(N):
            x1, y1 = contour[i]
            x2, y2 = contour[(i + n) % N]

            # Angle between gradient vectors (gx1, gy1) and (gx2, gy2)
            gx1 = GX[y1, x1]
            gy1 = GY[y1, x1]
            gx2 = GX[y2, x2]
            gy2 = GY[y2, x2]
            cos_angle = gx1 * gx2 + gy1 * gy2
            cos_angle /= (np.linalg.norm((gx1, gy1)) * np.linalg.norm((gx2, gy2)))
            angle = np.arccos(cos_angle)
            if cos_angle < 0:
                angle = np.pi - angle

            x1, y1 = contour[((2*i + n) // 2) % N]  # Get the middle point between i and (i + n)
            heatmap[y1, x1] = angle  # Use angle between gradient vectors as score
            measure.append((angle, x1, y1, gx1, gy1))

        _, x1, y1, gx1, gy1 = max(measure)  # Most pointed point for each contour

        # Possible to filter for those blobs with measure > val in heatmap instead.
        pointed_points.append((x1, y1, gx1, gy1))

    heatmap = cv2.GaussianBlur(heatmap, (3, 3), heatmap.max())
    return heatmap, pointed_points


def plot_points(image, pointed_points, radius=5, color=(255, 0, 0)):
    for (x1, y1, _, _) in pointed_points:
        cv2.circle(image, (x1, y1), radius, color, -1)

def main():
    I = cv2.imread("glLqt.jpg", 0)
    heatmap, pointed_points = compute_pointness(I, n=5)
    pl.figure()
    pl.imshow(heatmap, cmap=pl.cm.jet)
    pl.colorbar()
    I_color = cv2.cvtColor(I, cv2.COLOR_GRAY2RGB)
    plot_points(I_color, pointed_points)
    pl.figure()
    pl.imshow(I_color)


if __name__ == '__main__':
    main()

请注意,热图中越尖锐的点越亮。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenCV 中是否可以将局部曲率绘制为代表对象“指向性”的热图? 的相关文章

随机推荐