cv.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import cv2
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. # cv2.namedWindow('Image', cv2.WINDOW_NORMAL)
  5. def chose(contour):
  6. sm = cv2.arcLength(contour, True)
  7. approx = cv2.approxPolyDP(contour, sm*0.025, True)
  8. if (len(approx) == 7 or len(approx) == 8) and sm > 60:
  9. return 'circle'
  10. def recognize(image, shape):
  11. # =============== Находим большие синие круглишки =================
  12. hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
  13. binary = np.zeros(hsv.shape[:-1])
  14. binary[np.any(hsv > 190, axis=2)] = 1
  15. contours = cv2.findContours(binary.astype('uint8'), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[0]
  16. corner_left_up, corner_right_down = None, None
  17. for i,contour in enumerate(contours):
  18. if chose(contour) == 'circle':
  19. x = contour[:, 0, 0]
  20. y = contour[:, 0, 1]
  21. x_max, x_min, y_max, y_min = x.max(), x.min(), y.max(), y.min()
  22. if not corner_left_up or corner_left_up[0] < x_min or corner_left_up[1] < y_min:
  23. corner_left_up = (x_max, y_max)
  24. elif not corner_right_down or corner_right_down[0] > x_min or corner_right_down[1] > y_min:
  25. corner_right_down = (x_min, y_min)
  26. cv2.drawContours(image, contours, i, (0, 255, 0), 2)
  27. # ================= Бинаризируем полученное поле ===================
  28. image = image[corner_right_down[1]:corner_left_up[1],corner_right_down[0]:corner_left_up[0]]
  29. image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  30. thresh = cv2.adaptiveThreshold(image,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,3,2)
  31. binary = np.zeros(image.shape)
  32. binary[image < thresh] = 1
  33. binary = cv2.dilate(binary, None, iterations=2)
  34. contours = cv2.findContours(binary.astype('uint8'), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[0]
  35. newbinary = np.zeros(binary.shape)
  36. for contour in contours:
  37. cv2.drawContours(newbinary, [contour], -1, 1, -1)
  38. binary = cv2.erode(newbinary, None, iterations=5)
  39. binary = cv2.dilate(binary, None, iterations=2)
  40. # ================= Трансформируем доску в экран ===================
  41. desk_contour = np.float32([[0, binary.shape[0]], [0,0],
  42. [binary.shape[1], 0], [binary.shape[1], binary.shape[0]]])
  43. game_contour = np.float32([[0, shape[1]], [0, 0], [shape[0], 0], [shape[0], shape[1]]])
  44. mask = cv2.getPerspectiveTransform(desk_contour, game_contour)
  45. binary = cv2.warpPerspective(binary, mask, shape)
  46. # =================== Находим объекты ===================
  47. contours = cv2.findContours(binary.astype('uint8'), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[0]
  48. polys = []
  49. for contour in contours:
  50. eps = 0.044 * cv2.arcLength(contour, True)
  51. rect = cv2.minAreaRect(contour)
  52. box = cv2.boxPoints(rect)
  53. box = np.intp(box)
  54. approx = cv2.approxPolyDP(box, eps, True)
  55. approx = approx[:, 0, :].tolist()
  56. polys.append(approx)
  57. return polys
  58. if __name__ == "__main__":
  59. image = cv2.imread('falling_ball/image.png')
  60. print(recognize(image, (1200, 800)))