python - 如何从二值图像中找到四个点?
问题描述
我有一个像下面这样的图像,我想从这个图像中找到四个坐标(角)。
我试过下面的代码:
# dilate thresholded image - merges top/bottom
kernel = np.ones((3,3), np.uint8)
dilated = cv2.dilate(img, kernel, iterations=3)
# Finding contours for the thresholded image
contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
首先,我扩大了图像以填充散点部分并尝试从那里找出轮廓。但它给了我错误的输出。我能做些什么来找出四个角坐标?
解决方案
我通过将回归线扔到你的每一边并取他们的拦截点来找到你的观点。
首先,我导入东西并使用打开的 cv 找到轮廓点。
import numpy as np
import cv2
import matplotlib.pyplot as plt
from scipy.stats import linregress
from sympy import solve, symbols
import itertools
img = cv2.imread('ZrSqG.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
threshold, binarized_img = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
contours, hierarchy = cv2.findContours(binarized_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = (contours[1].reshape(-1,2)).T
现在我得到了一些最上面、最左边等点,然后把它们扔了一条线。然后我计算他们的拦截并将其全部绘制出来。
def interpolate_function(x,y):
line = interpolate(x,y)
return lambda x: x*line.slope+line.intercept
def interpolate(x,y):
idx = np.argsort(x)
line = linregress(x[idx], y[idx])
return line
def interception(line1, line2):
x = symbols('x')
x = solve(x*line1.slope+line1.intercept-(x*line2.slope+line2.intercept))[0]
return (x,x*line1[0]+line1[1])
idx_x = np.argsort(contours[0])
idx_y = np.argsort(contours[1])
left = [contours[0][idx_x[:30]], contours[1][idx_x[:30]]]
right = contours[0][idx_x[-10:]], contours[1][idx_x[-10:]]
top = contours[0][idx_y[:10]], contours[1][idx_y[:10]]
bottom = contours[0][idx_y[-30:]], contours[1][idx_y[-30:]]
contour_functions = [interpolate_function(*left), interpolate_function(*right),interpolate_function(*top), interpolate_function(*bottom)]
contour_function_eqs = [[interpolate(*left), interpolate(*right)],
[interpolate(*top), interpolate(*bottom)]]
for f in contour_functions:
t = np.linspace(0, img.shape[1], 10**4)
t = t[(0 < f(t)) & (f(t) < img.shape[0])]
plt.plot(t,f(t))
itersections = np.array([interception(line1, line2)
for line1, line2 in itertools.product(contour_function_eqs[0], contour_function_eqs[1])])
plt.scatter(itersections[:,0], itersections[:,1])
plt.imshow(img, cmap='gray')
或者,如果您更喜欢跟随左下部分,您只需通过重播来减少底部的点
bottom = contours[0][idx_y[-30:]], contours[1][idx_y[-30:]]
和
bottom = contours[0][idx_y[-10:]], contours[1][idx_y[-10:]]
推荐阅读
- python - 使用 ahk 库将击键发送到记事本
- mysql - 当一个数据有撇号标记时,ajax 请求出错(无效的 json 响应)
- python - 在 Networkx 中映射两个图
- r - 如果月-年组合不等于系统的月-年,则从同一月的去年值交换值的结果
- components - 如何在 Svelte 中的多个插槽和它们的父级之间共享状态
- apache-pig - 阿帕奇猪查询
- sql - EXECUTE ('CALL SCHEMA.PROC')、CALL SCHEMA.PROC 和 EXCEUTE 之间是否存在性能差异
- python - 计算派生列
- sql - 对于具有重复键的行,如何获得最长记录?
- javascript - 如何检测推送菜单外的点击并关闭菜单