pic_segment.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. # -*- coding:utf-8 -*-
  2. import os,sys,time
  3. import cv2 as cv
  4. import numpy as np
  5. from ssat_sdk.utils import LoggingUtil
  6. from ssat_sdk.picture import image_util
  7. class PicSegment():
  8. def __init__(self):
  9. pass
  10. '''
  11. 在传入的图片上,查找指定bgr颜色框矩形区域,返回矩形区域的坐标
  12. :param picPath:图片路径
  13. :param bgr:颜色值
  14. :return result, contourRect:result=True/False, contourRect:矩形区域
  15. '''
  16. def findAreaByColor(self, srcImg, cropArea, bgr, offset=20, minPeri=0, maxPeri=0, minArea=0, maxArea=0,
  17. morphology=[]):
  18. # 获取rgb二值图;
  19. img_binary, cropArea = self.getBGRBinaryImage(srcImg, cropArea, bgr, offset)
  20. if img_binary is None:
  21. return False, None
  22. # 查找符合要求的外轮廓;
  23. # opencv3开始,有3个返回值:img, countours, hierarchy
  24. contours = cv.findContours(img_binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)[1]
  25. # 是否查找最大轮廓;
  26. bFindMaxContour = False
  27. # 如果周长、面积都一样,只返回最大轮廓;
  28. if minPeri == maxPeri and minArea == maxArea:
  29. bFindMaxContour = True
  30. contourRect = []
  31. maxContour = None # 最大轮廓;
  32. tempArea = 0
  33. # 过滤掉不符合要求的轮廓;
  34. x, y, w, h, result = 0, 0, 0, 0, False
  35. for cnt in contours:
  36. # 面积;
  37. area = cv.contourArea(cnt)
  38. # 周长;
  39. perimeter = cv.arcLength(cnt, True)
  40. # print "area=%ld, perimeter=%ld"%(area, perimeter)
  41. if bFindMaxContour == True:
  42. # 获取最大轮廓;
  43. if tempArea < area:
  44. tempArea = area
  45. maxContour = cnt
  46. else:
  47. # print area,perimeter
  48. # 获取满足条件的值;
  49. if area >= minArea and area <= maxArea and perimeter >= minPeri and perimeter <= maxPeri:
  50. # 直边矩形,(x,y)为矩形左上角的坐标,(w,h)是矩形的宽和高;
  51. x, y, w, h = cv.boundingRect(cnt)
  52. # 在区域内截图判断;
  53. if cropArea is not None:
  54. x = x + cropArea[0]
  55. y = y + cropArea[1]
  56. contourRect = [x, y, x + w, y + h]
  57. result = True
  58. break
  59. # endif
  60. # endfor
  61. if bFindMaxContour == True and maxContour is not None:
  62. result = True
  63. # 最大轮廓的矩形坐标;
  64. x, y, w, h = cv.boundingRect(maxContour)
  65. # 在区域内截图判断;
  66. if cropArea is not None:
  67. x = x + cropArea[0]
  68. y = y + cropArea[1]
  69. contourRect = [x, y, x + w, y + h]
  70. # 只返回结果、轮廓坐标;
  71. return result, contourRect
  72. '''
  73. 不做任何图片补足处理的颜色区域处理,和二值化图片获取
  74. '''
  75. def getBGRBinaryImage(self, srcImg, cropArea, bgr, offset=20):
  76. # 读取图片;
  77. if srcImg is None:
  78. return None,None
  79. # 如果截图区域空,使用原图大小;
  80. if cropArea is not None or cropArea.__len__() == 0:
  81. cropArea = [0, 0, srcImg.shape[1], srcImg.shape[0]]
  82. img_crop = None
  83. # 只保留区域部分;
  84. try:
  85. img_crop = image_util.cutImage(srcImg, cropArea)
  86. except:
  87. img_crop = srcImg
  88. subImg = self.subImgBgr(img_crop, bgr)
  89. cv.imwrite(r'd:\\subImg.png', subImg)
  90. subImg_wh1 = np.where((subImg > -offset) & (subImg < offset), np.uint8(0), np.uint8(255))
  91. cv.imwrite(r'd:\\subImg_wh1.png', subImg_wh1)
  92. # 将图处转成灰阶
  93. img_gray = cv.cvtColor(subImg_wh1, cv.COLOR_BGR2GRAY)
  94. # 反转灰度值,以便适合查找轮廓;
  95. img_gray = np.where((img_gray < -offset) | (img_gray > offset), np.uint8(0), np.uint8(255))
  96. # 输出结果图片;
  97. cv.imwrite(r'd:\\img_gray.png', img_gray)
  98. # 使用灰度图求得二值化图;
  99. thresh = cv.threshold(img_gray, 1, 255, cv.THRESH_BINARY)[1]
  100. # 返回二值化图;
  101. return thresh, cropArea
  102. '''
  103. 在原有图片,减去固定的BGR颜色值,用于后续的颜色筛选.返回减去bgr的图片。
  104. '''
  105. def subImgBgr(self, bgrImg, bgr):
  106. imgArr = np.asarray(bgrImg).astype(np.int16)
  107. bgrArr = np.asarray(bgr).astype(np.int16)
  108. # 矩阵相减;
  109. subImg = imgArr - bgrArr
  110. return subImg