玩命加载中 . . .

OpenCV_Panel


import cv2 as cv
from matplotlib import pyplot as plt
import numpy as np
from numpy.linalg import inv

""" 求两直线交点 """
def intersection(line1, line2):
    # [x1, y1, x2, y2]
    a1 = line1[1] - line1[3]    # a = y1 - y2
    b1 = line1[2] - line1[0]    # b = x2 - x1
    c1 = line1[0] * line1[3] - line1[2] * line1[1]    # c = x1 * y2 - x2 * y1
    a2 = line2[1] - line2[3]    # a = y1 - y2
    b2 = line2[2] - line2[0]    # b = x2 - x1
    c2 = line2[0] * line2[3] - line2[2] * line2[1]    # c = x1 * y2 - x2 * y1
    A = np.array([[a1, b1], [a2, b2]])
    B = np.array([[c1], [c2]])
    pt = np.dot(inv(A), -B)
    x = pt[0, 0]
    y = pt[1, 0]
    return [x, y]


src = cv.imread("images/2.png")
mat = src.copy()
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
blur = cv.blur(gray, (5, 5))
# plt.figure(1)
# plt.imshow(blur, cmap="binary")

kernel = np.ones((10, 10), np.int8)

dilate = cv.dilate(blur, kernel)

""" 二值化 """
ret, binary = cv.threshold(dilate, 100, 120, cv.THRESH_BINARY_INV)
# plt.figure(2)
# plt.imshow(binary, cmap="binary")

""" 求轮廓 """
contours, hierarchy = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

# print('len:', len(contours))
cnt = contours[0]
# cv.drawContours(src, [cnt], -1, (0, 0, 255), 2)
""" 找到满足周长条件的轮廓 """
for i in range(len(contours)):
    cnt = contours[i]
    perimeter = cv.arcLength(cnt, True)
    if 2500 < perimeter < 3500:
        print(perimeter)
        # cv.drawContours(src, [cnt], -1, (0, 255, 255), 2)
        break
# plt.figure(2)
# plt.imshow(src[:, :, ::-1])
""" 求凸包 """
hull = cv.convexHull(cnt)

img = np.ones((720, 1280, 3), dtype=np.uint8)

# print(type(gray))   # <class 'numpy.ndarray'>
# print(gray.shape)   # (720, 1280)
# print(type(img))    # <class 'numpy.ndarray'>
# print(img.shape)    # (720, 1280)

# cv.drawContours(src, [hull], -1, (255, 0, 0), 3)
# print(len(hull))
""" 在另一张图上画出凸包 """
cv.drawContours(img, [hull], -1, (0, 0, 255), 2)
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

""" 二值化 """
_, img_binary = cv.threshold(img_gray, 50, 100, cv.THRESH_BINARY)
plt.figure(3)
plt.imshow(img_binary, cmap="binary")
#### cv.imwrite("images/img.png", img_binary)

""" 霍夫线检测 """
lines = cv.HoughLines(img_binary, 1.0, np.pi/180, 250)

print(lines.shape)      # (8, 1, 2)
lines = np.squeeze(lines)
print(lines.shape)      # (8, 2)

""" K-means对四种线分类 """
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 10, 1.0)
ret,label,center = cv.kmeans(lines, 4, None, criteria, 10, cv.KMEANS_RANDOM_CENTERS)
# print(center.shape)   # (4, 2)
line_point = []
for i in range(center.shape[0]):
    rho, theta = center[i]
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = rho * a
    y0 = rho * b
    x1 = int(x0 + 2000 * (-b))
    y1 = int(y0 + 2000 * a)
    x2 = int(x0 - 2000 * (-b))
    y2 = int(y0 - 2000 * a)
    line_point.append([x1, y1, x2, y2])
    cv.line(img, (x1, y1), (x2, y2), (255, 0, 255), 4)
# print(line_point)
""" 求4条线的4个交点 """
pt = []
for i in range(2):
    pt.append(intersection(line_point[i], line_point[2]))
    pt.append(intersection(line_point[i], line_point[3]))
print(pt)
points = np.array(pt, dtype=int)
print(points.shape)     # (4, 2)
print(points)
# for i in range(points.shape[0]):
#     cv.circle(img, (points[i, 0], points[i, 1]), 8, (0, 255, 0), -1)
""" 画出4个交点 """
for pt in points:
    cv.circle(img, (pt[0], pt[1]), 6, (0, 255, 0), -1)

plt.figure(5)
plt.imshow(img)
# cv.imwrite("images/lines.png", img)

""" 对4个交点进行排序,因为分类的顺序是随机的 """
idx = np.lexsort([points[:, 0]])
tr_points = points[idx, :]
print(tr_points)

""" 利用找到的4隔点进行透射变换 """
dst_width = 800
dst_height = 600
pts1 = np.float32([tr_points[0], tr_points[3], tr_points[2], tr_points[1]])
pts2 = np.float32([[0, 0], [dst_width, 0], [dst_width, dst_height], [0, dst_height]])
M = cv.getPerspectiveTransform(pts1, pts2)
dst = cv.warpPerspective(mat, M, (dst_width, dst_height))
plt.figure(6)
plt.imshow(dst[:, :, ::-1])
cv.imwrite('images/dst_2.png', dst)


plt.show()
test
1.原图
test
2.凸包
test
3. 霍夫线检测与交点
test
4.透射变换

文章作者: kunpeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kunpeng !
  目录