图像检测,检测胶带在电路板上贴的位置是否正确。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
3.4 KiB

  1. # coding=utf-8
  2. import cv2
  3. import numpy as np
  4. import math
  5. # 修改图像的对比度,coefficent>0, <1降低对比度,>1提升对比度 建议0-2
  6. def change_contrast(img, coefficent):
  7. imggray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  8. m = cv2.mean(img)[0]
  9. graynew = m + coefficent * (imggray - m)
  10. img1 = np.zeros(img.shape, np.float32)
  11. k = np.divide(graynew, imggray, out=np.zeros_like(graynew), where=imggray != 0)
  12. img1[:, :, 0] = img[:, :, 0] * k
  13. img1[:, :, 1] = img[:, :, 1] * k
  14. img1[:, :, 2] = img[:, :, 2] * k
  15. img1[img1 > 255] = 255
  16. img1[img1 < 0] = 0
  17. return img1.astype(np.uint8)
  18. # 修改图像的亮度,brightness取值0~2 <1表示变暗 >1表示变亮
  19. def change_brightness(img, brightness):
  20. [averB, averG, averR] = np.array(cv2.mean(img))[:-1] / 3
  21. k = np.ones((img.shape))
  22. k[:, :, 0] *= averB
  23. k[:, :, 1] *= averG
  24. k[:, :, 2] *= averR
  25. img = img + (brightness - 1) * k
  26. img[img > 255] = 255
  27. img[img < 0] = 0
  28. return img.astype(np.uint8)
  29. # 对图像二值化并取中值滤波
  30. def threshold_img(image):
  31. gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  32. retval, dst = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)
  33. img_median = cv2.medianBlur(dst, 3)
  34. return img_median
  35. # 腐蚀图像
  36. def corrosion_img(image):
  37. # 腐蚀操作会把裂痕也消除
  38. kernel = np.ones((9, 9), dtype=np.uint8)
  39. opening = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel, 1)
  40. return opening
  41. # 找出最右侧的近似竖直直线 通过直线与水平的角度判断是否倾斜 大于容错率的竖直 小于容错率的倾斜
  42. def lines_img(image):
  43. slopes = []
  44. yErrorRange = 3
  45. xErrorRange = 3
  46. minLength = 20
  47. # 创建一个LSD对象
  48. lsd = cv2.createLineSegmentDetector(0)
  49. # 执行检测结果
  50. dlines = lsd.detect(image)
  51. # 绘制检测结果
  52. for dline in dlines[0]:
  53. x0 = int(round(dline[0][0]))
  54. y0 = int(round(dline[0][1]))
  55. x1 = int(round(dline[0][2]))
  56. y1 = int(round(dline[0][3]))
  57. length = math.hypot(x1 - x0, y1 - y0)
  58. if (x0 > 605 and x1 > 605):
  59. # print((x0, y0), (x1, y1))
  60. # 需要根据角坐标排除 横向线,针对纵向线判断是否有倾斜
  61. # 过滤横线
  62. if not (abs(x1 - x0) > xErrorRange and abs(y1 - y0) < yErrorRange):
  63. # 过滤线段长度
  64. if not (length < minLength):
  65. if x1 - x0 != 0:
  66. k = abs(y1 - y0) / abs(x1 - x0)
  67. angle = math.atan(k) * 180 / math.pi
  68. slopes.append(angle)
  69. print(angle)
  70. # cv2.line(img0, (x0, y0), (x1,y1), (0,255,0), 1, cv2.LINE_AA)
  71. # 有小于85度的就证明胶带倾斜了
  72. threshold = 85
  73. res = any(x < threshold for x in slopes)
  74. if res:
  75. print("胶带倾斜")
  76. else:
  77. print("胶带正确")
  78. def detectionImg():
  79. # 读取输入图片
  80. img = cv2.imread("img/a.png")
  81. l = 0
  82. c = 34
  83. # 亮度 -1~1
  84. imgBrightness = change_brightness(img, float(l - 50) / float(50))
  85. # 对比度 0~2
  86. img0 = change_contrast(imgBrightness, c / 50)
  87. thresholdImg = threshold_img(img0)
  88. corrosionImg = corrosion_img(thresholdImg)
  89. lines_img(corrosionImg)
  90. # 显示并保存结果
  91. cv2.imshow("gray", corrosionImg)
  92. cv2.imshow("lines", img0)
  93. cv2.waitKey(0)
  94. cv2.destroyAllWindows()
  95. if __name__ == '__main__':
  96. detectionImg()