我是靠谱客的博主 精明萝莉,最近开发中收集的这篇文章主要介绍python-cv2:求直线和轮廓的交点,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

      • 1.读取图片,阈值处理
      • 2.获取轮廓
      • 3.直线和boundingbox
      • 3.测试枚举线段点
      • 4.完整测试代码

实例图片镇楼
在这里插入图片描述

1.读取图片,阈值处理

# 读取图片并灰度值化
img = cv2.imread('d:1.jpg', 0)
# 二值化,过滤掉噪音
img = np.where(img < 100, 0, 255).astype(np.uint8)
cv2.imshow('0', img)
cv2.waitKey(0)

在这里插入图片描述

2.获取轮廓

conts, _ = cv2.findContours(img, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)

在这里插入图片描述

3.直线和boundingbox

如给定一条直线,用点p1(20, 200),p2(340, 90)来表示。若已知在这条直线上位于轮廓2外侧的2个点A,B,就可枚举线段AB上所有的点,推断这些点和轮廓的关系(轮廓上,轮廓内,轮廓外)。如何求解点A和B? 为了提高枚举速度,可先求轮廓的boundingbox,直线和boundingbox的交点即A和B点。

x, y, w, h = cv2.boundingRect(conts[0])
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 1)
# 随便画一条直线
p1, p2 = (20, 200), (340, 90)
if p2[0] != p1[0]:  # 若存在斜率 y=kx+b
    k = (p2[1] - p1[1]) / (p2[0] - p1[0])
    b = p1[1] - p1[0] * k
    # 求解直线和boundingbox的交点A和B
    pa, pb = (x, int(k * x + b)), ((x + w), int(k * (x + w) + b))
else:  # 若斜率不存在,垂直的直线
    pa, pb = (p1[0], y), (p1[0], y + h)
cv2.circle(img, pa, 2, (0, 255, 255), 2)
cv2.circle(img, pb, 2, (0, 255, 255), 2)
cv2.putText(img, 'A', (pa[0] - 10, pa[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 1)
cv2.putText(img, 'B', (pb[0] + 10, pb[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 1)
cv2.line(img, p1, p2, (255, 255, 0), 1)

在这里插入图片描述

3.测试枚举线段点

C++版opencv中枚举点的函数有LineIterator,但cv2中好像无类似函数,因此使用skimage.draw.line来代替。(PS:若枚举的点全都不在轮廓上,可使用1内1外的中点近似)

# 枚举2点之间的线段点
for pt in zip(*line(*pa, *pb)):
    if cv2.pointPolygonTest(conts[0], pt, False) == 0:  # 若点在轮廓上
        cv2.circle(img, pt, 2, (0, 0, 255), 2)

在这里插入图片描述

4.完整测试代码

import cv2, os
import numpy as np
from skimage.draw import line

# 读取图片并灰度值化
img = cv2.imread('d:1.jpg', 0)
# 二值化,过滤掉噪音
img = np.where(img < 100, 0, 255).astype(np.uint8)
# 假定只有一个轮廓conts[0]
conts, _ = cv2.findContours(img, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)
# 颜色区分,把原图再转为BGR
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
cv2.drawContours(img, conts, -1, (0, 255, 0), 1)
x, y, w, h = cv2.boundingRect(conts[0])
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 1)
# 随便画一条直线
p1, p2 = (20, 200), (340, 90)
if p2[0] != p1[0]:  # 若存在斜率 y=kx+b
    k = (p2[1] - p1[1]) / (p2[0] - p1[0])
    b = p1[1] - p1[0] * k
    # 求解直线和boundingbox的交点A和B
    pa, pb = (x, int(k * x + b)), ((x + w), int(k * (x + w) + b))
else:  # 若斜率不存在,垂直的直线
    pa, pb = (p1[0], y), (p1[0], y + h)
cv2.circle(img, pa, 2, (0, 255, 255), 2)
cv2.circle(img, pb, 2, (0, 255, 255), 2)
cv2.putText(img, 'A', (pa[0] - 10, pa[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 1)
cv2.putText(img, 'B', (pb[0] + 10, pb[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 1)
cv2.line(img, p1, p2, (255, 255, 0), 1)
# 枚举2点之间的线段点
for pt in zip(*line(*pa, *pb)):
    if cv2.pointPolygonTest(conts[0], pt, False) == 0:  # 若点在轮廓上
        cv2.circle(img, pt, 2, (0, 0, 255), 2)
cv2.imshow('0', img)
cv2.waitKey(0)

reference:
https://stackoverflow.com/questions/32328179/opencv-3-0-lineiterator
https://zhuanlan.zhihu.com/p/46055147

最后

以上就是精明萝莉为你收集整理的python-cv2:求直线和轮廓的交点的全部内容,希望文章能够帮你解决python-cv2:求直线和轮廓的交点所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部