在OpenCV中是否可以将局部曲率绘制为表示对象"点"的热图?

use*_*339 4 python opencv image-processing

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

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

我的目标是测量一个对象的"尖锐度",这样我就可以从尖端绘制一个向量到相反的非尖端.对于我的对象,我碰巧知道尖端的一面是顶部.

如果其他技术在表示"点"性方面比曲率更有效,可以随意提出.

在此输入图像描述

在此输入图像描述

在此输入图像描述

lig*_*ist 8

编辑:修复了以前版本中的错误.

我使用第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()
Run Code Online (Sandbox Code Playgroud)

检测点. 每个轮廓一个

热图

请注意,热图中更尖锐的点更亮.