python - 在 openCV 和 python 中计算二值图像中的曲线、角度和直线

标签 python image opencv image-processing

我想编写一个工具来查找图像中每个有界对象内的角度、曲线和直线的数量。 所有输入图像均为白底黑字,并且全部代表字符。

如图所示,对于每个有界区域,记录每个形状的出现。最好能够有一个阈值,规定曲线必须弯曲到什么程度才能被视为曲线而不是角度等。直线和角度也是如此。

我已经使用霍夫线变换来检测其他图像上的直线,它可能与我认为的一些东西结合使用。

我对 opencv 之外的其他库持开放态度 - 这只是我的一些经验。

提前致谢

IMAGE: Occurences of shape in the letters

编辑: 因此,根据 Markus 的回答,我使用 findContours()CHAIN_APPROX_SIMPLE 编写了一个程序。

输入“k”会产生一个有点奇怪的结果,它正确地识别了角度周围的一些点,但“腿”(下部对角线部分)上有很多很多点。我不确定如何将其分为直线、角度和曲线。

代码:

import numpy as np

img = cv2.imread('Helvetica-K.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (3, 3), 0)
edges = cv2.Canny(blurred, 50, 150, apertureSize=3)
ret, thresh = cv2.threshold(gray, 180, 255, cv2.THRESH_BINARY_INV)

contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
#cv2.drawContours(img, contours, 0, (0,255,0), 1)

#Coordinates of each contour
for i in range(len(contours[0])):
    print(contours[0][i][0][0])
    print(contours[0][i][0][1])
    cv2.circle(img, (contours[0][i][0][0], contours[0][i][0][1]), 2, (0,0,255), -1)

cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

图片示例: K-helvitica

最佳答案

您可以使用findContours使用选项CHAIN_APPROX_SIMPLE

  • 角度小于某个阈值的点是角点。
  • 角度超过某个阈值的点位于直线上,应将其删除。
  • 距离超过某个阈值的两个相邻点是直线的端点。
  • 被识别为角点的两个相邻点是直线的端点。
  • 所有其他点都属于一些曲线细节。

更新:

这是一些您可以开始使用的代码。它展示了如何平滑直线,如何将多个角点合并为一个,以及如何计算每个点的距离和角度。要达到所需的结果,您还有一些工作要做,但我希望它能朝着正确的方向发展。

import numpy as np
import numpy.linalg as la
import cv2


def get_angle(p1, p2, p3):
    v1 = np.subtract(p2, p1)
    v2 = np.subtract(p2, p3)
    cos = np.inner(v1, v2) / la.norm(v1) / la.norm(v2)
    rad = np.arccos(np.clip(cos, -1.0, 1.0))
    return np.rad2deg(rad)


def get_angles(p, d):
    n = len(p)
    return [(p[i], get_angle(p[(i-d) % n], p[i], p[(i+d) % n])) for i in range(n)]


def remove_straight(p):
    angles = get_angles(p, 2)                     # approximate angles at points (two steps in path)
    return [p for (p, a) in angles if a < 170]    # remove points with almost straight angles


def max_corner(p):
    angles = get_angles(p, 1)                     # get angles at points
    j = 0

    while j < len(angles):                        # for each point
        k = (j + 1) % len(angles)                 # and its successor
        (pj, aj) = angles[j]
        (pk, ak) = angles[k]

        if la.norm(np.subtract(pj, pk)) <= 4:     # if points are close
            if aj > ak:                           # remove point with greater angle
                angles.pop(j)
            else:
                angles.pop(k)
        else:
            j += 1

    return [p for (p, a) in angles]


def main():
    img = cv2.imread('abc.png')
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(gray, 180, 255, cv2.THRESH_BINARY_INV)

    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    for c in contours:                  # for each contour
        pts = [v[0] for v in c]         # get pts from contour
        pts = remove_straight(pts)      # remove almost straight angles
        pts = max_corner(pts)           # remove nearby points with greater angle
        angles = get_angles(pts, 1)     # get angles at points

        # draw result
        for (p, a) in angles:
            if a < 120:
                cv2.circle(img, p, 3, (0, 0, 255), -1)
            else:
                cv2.circle(img, p, 3, (0, 255, 0), -1)

    cv2.imwrite('out.png', img)
    cv2.destroyAllWindows()


main()

enter image description here

关于python - 在 openCV 和 python 中计算二值图像中的曲线、角度和直线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72099560/

相关文章:

python - 为什么 Python 无法请求解析 TikTok API 数据?

image - 如何在python flask服务器中保存base64图像

matlab - 逐像素比较图像

python - 用于 AES 256 加密的(纯)Python 库是什么?

python - 如何禁用查询缓存?

Python Pandas 错误标记数据

javascript - 图片显示中的浏览器依赖问题

image - 如何在 MATLAB 中将灰度矩阵转换为 RGB 矩阵?

c++ - Opencv C++ : Display pixel value using cursor of the image before applying colormap

opencv - 什么是 OpenCV 中的 Debug 模式和 Release 模式?