先简述代码设计思路流程,完整代码贴在最后。
1.首先要知道弧线就是圆的一部分,所以需要通过三个点找到对应的圆方程:
这一步就需要依靠数学公式计算。
2.找到圆方程之后,如何确定所需要的弧线是哪一段?
根据中间点和开始结束两点组成的直线进行位置判断,绘制出所需的弧线段。
3.辅助功能:鼠标点击绘图。
效果图:
import cv2
import numpy as np
arc = cv2.imread('roi.png')
xy_arc = []
xx = []
yy = []
xy = []
def darc(event, x, y, flag, param):
global xy_arc
global xy
global xx
global yy
if event == cv2.EVENT_LBUTTONUP:
xy_arc.append((x, y))
cv2.circle(arc, (x, y), 1, (0, 0, 255), -1)
if len(xy_arc) == 3:
a = xy_arc[0][0] - xy_arc[1][0]
b = xy_arc[0][1] - xy_arc[1][1]
c = xy_arc[0][0] - xy_arc[2][0]
d = xy_arc[0][1] - xy_arc[2][1]
a1 = ((xy_arc[0][0] * xy_arc[0][0] - xy_arc[1][0] * xy_arc[1][0]) +
(xy_arc[0][1] * xy_arc[0][1] - xy_arc[1][1] * xy_arc[1][1])) / 2.0
a2 = ((xy_arc[0][0] * xy_arc[0][0] - xy_arc[2][0] * xy_arc[2][0]) +
(xy_arc[0][1] * xy_arc[0][1] - xy_arc[2][1] * xy_arc[2][1])) / 2.0
theta = b * c - a * d
if abs(theta) < 1e-7:
raise RuntimeError('There should be three different x & y !')
x0 = (b * a2 - d * a1) / theta
y0 = (c * a1 - a * a2) / theta
r = np.sqrt(pow((xy_arc[0][0] - x0), 2) + pow((xy_arc[0][1] - y0), 2))
black = np.zeros([arc.shape[0], arc.shape[1], 3], np.uint8)
cv2.circle(black, (round(x0), round(y0)), round(r), (255, 0, 0), thickness=1)
for i in range(0, black.shape[0]):
for j in range(0, black.shape[1]):
if black.item(i, j, 0) == 255:
xy.append((i, j))
'''for point in xy: # point[0]为y坐标,point[1]为x坐标。
if xy_arc[0][0] < xy_arc[1][0] and xy_arc[2][0] < xy_arc[1][0]:
if point[1] > xy_arc[0][0] and point[0] < xy_arc[1][1] or \
point[1] > xy_arc[2][0] and point[0] > xy_arc[1][1]:
xx.append(point)
if xy_arc[0][0] < xy_arc[1][0] < xy_arc[2][0]:
if xy_arc[1][0] > point[1] > xy_arc[0][0] and point[0] < xy_arc[1][1] or \
xy_arc[2][0] > point[1] > xy_arc[1][0] and point[0] < xy_arc[2][1]:
xx.append(point)
if xy_arc[0][0] > xy_arc[1][0] and xy_arc[2][0] > xy_arc[1][0]:
if point[1] < xy_arc[0][0] and point[0] < xy_arc[1][1] or \
point[1] < xy_arc[2][0] and point[0] > xy_arc[1][1]:
xx.append(point)
if xy_arc[0][0] > xy_arc[1][0] > xy_arc[2][0]:
if xy_arc[0][0] > point[1] and point[0] < xy_arc[1][1] or \
xy_arc[1][0] > point[1] and point[0] < xy_arc[2][1]:
xx.append(point)
for point in xx:
arc.itemset((point[0], point[1], 0), 255)
arc.itemset((point[0], point[1], 1), 0)
arc.itemset((point[0], point[1], 2), 0)''' # 方法一
K = (xy_arc[2][1]-xy_arc[0][1])/(xy_arc[2][0]-xy_arc[0][0])
B = xy_arc[0][1]-K*xy_arc[0][0]
for point in xy:
if point[1]*K+B > point[0]:
xx.append(point)
if point[1]*K+B < point[0]:
yy.append(point)
if K*xy_arc[1][0]+B > xy_arc[1][1]:
for point in xx:
arc.itemset((point[0], point[1], 0), 255)
arc.itemset((point[0], point[1], 1), 0)
arc.itemset((point[0], point[1], 2), 0)
if K*xy_arc[1][0]+B < xy_arc[1][1]:
for point in yy:
arc.itemset((point[0], point[1], 0), 255)
arc.itemset((point[0], point[1], 1), 0)
arc.itemset((point[0], point[1], 2), 0)
xy_arc = []
xy = []
xx = []
yy = []
cv2.imshow('arc', arc)
cv2.namedWindow('arc', cv2.WINDOW_GUI_NORMAL + cv2.WINDOW_KEEPRATIO)
cv2.resizeWindow('arc', (1200, 1000),)
cv2.setMouseCallback('arc', darc)
cv2.imshow('arc', arc)
cv2.waitKey(0)