image_util.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. # -*- coding:utf-8 -*-
  2. import os, sys, time
  3. import inspect
  4. import cv2 as cv
  5. import numpy as np
  6. from ssat_sdk.utils import LoggingUtil
  7. pyFileName = os.path.split(__file__)[-1]
  8. def get_current_function_name():
  9. return inspect.stack()[1][3]
  10. '''
  11. 按照坐标系调整区域数值
  12. :param areaRXDY:二维区域。坐标系:x轴:水平向右,y轴:纵向向下
  13. :return areaDXRY:二维区域。坐标系:x轴:纵向向下,y轴:水平向右
  14. '''
  15. def coordinateRXDY2DXRY(areaRXDY):
  16. areaDXRY = []
  17. areaDXRY.append(areaRXDY[1])
  18. areaDXRY.append(areaRXDY[0])
  19. areaDXRY.append(areaRXDY[3])
  20. areaDXRY.append(areaRXDY[2])
  21. return areaDXRY
  22. '''
  23. 截取图片区域。
  24. :param area:二维区域。area按照常规x,y坐标描述。示例:[x1,y1,x2,y2]. 点(x1,y1)为矩形左上角,点(x2,y2)为矩形右下角。
  25. '''
  26. def cutMat(srcimg, area):
  27. try:
  28. mat_area = coordinateRXDY2DXRY(area)
  29. # print "cutMat:mat_area:", mat_area
  30. imgArr = np.array(srcimg)
  31. return imgArr[int(mat_area[0]):int(mat_area[2]),int(mat_area[1]):int(mat_area[3])]
  32. except Exception, e:
  33. LoggingUtil.getDebugLogger().info(pyFileName, "image_util", get_current_function_name(), 'ERROR:截图异常:'+str(e))
  34. return None
  35. '''
  36. # 描述:裁剪图片,返回指定裁剪区域的图片;
  37. # 参数:
  38. # srcimg:opencv.imread打开的对象。
  39. # area: 要裁剪的区域,示例:[x1,y1,x2,y2]. 点(x1,y1)为矩形左上角,点(x2,y2)为矩形右下角。
  40. #
  41. # 返回:成功返回裁剪区域的图片对象,否则返回None
  42. #
  43. # 注意:相对cutMat来说,少一步坐标转换。
  44. # '''
  45. def cutImage(srcimg, area):
  46. try:
  47. return np.array(srcimg[area[1]:area[3]+1, area[0]:area[2]+1])
  48. except Exception,e:
  49. LoggingUtil.getDebugLogger().info(pyFileName, "image_util", get_current_function_name(), 'ERROR:裁剪图片异常:'+str(e))
  50. return None
  51. '''
  52. # 描述:裁剪图片,返回指定裁剪区域的图片;
  53. # 参数:
  54. # imgPath:图片路径
  55. # area: 要裁剪的区域,示例:[x1,y1,x2,y2]. 点(x1,y1)为矩形左上角,点(x2,y2)为矩形右下角。
  56. #
  57. # 返回:成功返回裁剪区域的图片对象,否则返回None
  58. #
  59. # 注意:相对cutMat来说,少一步坐标转换。
  60. # '''
  61. def cutImageByPath(imgPath, area):
  62. srcimg = cv.imread(imgPath)
  63. try:
  64. return np.array(srcimg[area[1]:area[3], area[0]:area[2]])
  65. except Exception,e:
  66. LoggingUtil.getDebugLogger().info(pyFileName, "image_util", get_current_function_name(), 'ERROR:裁剪图片异常:'+str(e))
  67. return None
  68. def saveCropPic(srcPic, destPic, area):
  69. srcImg = cv.imread(srcPic)
  70. if srcImg is None:
  71. LoggingUtil.getDebugLogger().info(pyFileName, "image_util", get_current_function_name(), 'SDK:打开图像返回空对象,文件可能不存在或无权限打开')
  72. return False
  73. if len(area) != 4:
  74. LoggingUtil.getDebugLogger().info(pyFileName, "image_util", get_current_function_name(), 'SDK:给定的区域坐标无效:'+str(area))
  75. return False
  76. destImg = cutMat(srcImg, area)
  77. if destImg is None:
  78. LoggingUtil.getDebugLogger().info(pyFileName, "image_util", get_current_function_name(), 'SDK:截图失败:')
  79. return False
  80. cv.imwrite(destPic,destImg)
  81. return True
  82. def saveCropImg(srcImg, destPic, area):
  83. destImg = cutMat(srcImg, area)
  84. cv.imwrite(destPic,destImg)
  85. return True
  86. def cutImgWithRate(srcImg, destPic, rateArea):
  87. height, width, dim = srcImg.shape
  88. print "srcImg: height, width:", height, width, rateArea
  89. dest_x1 = int(width * rateArea[0])
  90. dest_x2 = int(width * rateArea[2])
  91. dest_y1 = int(height * rateArea[1])
  92. dest_y2 = int(height * rateArea[3])
  93. print "dest: dest_x1,dest_y1, dest_x2, dest_y2:", dest_x1,dest_y1, dest_x2, dest_y2
  94. destImg = cutMat(srcImg, (dest_x1,dest_y1, dest_x2, dest_y2))
  95. cv.imwrite(destPic, destImg)
  96. def cutPicWithRate(srcPic, destPic, rateArea):
  97. srcImg = cv.imread(srcPic)
  98. cutImgWithRate(srcImg, destPic, rateArea)
  99. '''
  100. 截取选中区域以外的图片
  101. '''
  102. def saveRetCropPic(srcPic, area):
  103. srcImg = cv.imread(srcPic)
  104. return saveRetCropImg(srcImg, area)
  105. def saveRetCropImg(srcImg, area):
  106. # print "saveRetCropImg,area:",area
  107. height,width,chNum = srcImg.shape
  108. area1 = [0,0,area[0], height]
  109. area2 = [area[0],0,area[2], area[1]]
  110. area3 = [area[0], area[3],area[2], height]
  111. area4 = [area[2],0,width, height]
  112. rectList = []
  113. addRect2List(rectList, area1)
  114. addRect2List(rectList, area2)
  115. addRect2List(rectList, area3)
  116. addRect2List(rectList, area4)
  117. imgList = []
  118. for rect in rectList:
  119. img = cutMat(srcImg, rect)
  120. imgList.append(img)
  121. return imgList
  122. '''
  123. 根据设定的灰阶阈值,保存一张新图片,并返回img对象。
  124. 原图像是BGR模式
  125. '''
  126. def saveThresholdPicImg(srcImg,threshLow,threshTop, thresholdType):
  127. # print u"转成灰阶图;"
  128. img_gray = cv.cvtColor(srcImg, cv.COLOR_BGR2GRAY)
  129. # print u"转成二值化;"
  130. ret, img_threshold = cv.threshold(img_gray, threshLow, threshTop, thresholdType)
  131. return img_threshold
  132. '''
  133. 检测rect是否正确,正确才添加到rectList
  134. '''
  135. def addRect2List(rectList, rect):
  136. # print "addRect2List,rect:",rect
  137. if (rect[0] <> rect[2]) and (rect[1] <> rect[3]):
  138. rectList.append(rect)
  139. def caculateLinLen(line):
  140. dx = abs(line[0] - line[2])
  141. dy = abs(line[1]-line[3])
  142. # print "caculateLinLen:",dx,dy
  143. lineLen = np.sqrt(np.square(dx) + np.square(dy))
  144. return lineLen
  145. class ImageUtil():
  146. def __init__(self):
  147. pass
  148. '''
  149. 根据传入的图像对象,逆时针旋转角度
  150. '''
  151. def rotaImg(self, srcImg, angle):
  152. height, width, color = srcImg.shape
  153. M = cv.getRotationMatrix2D(((height-1)/2.0,(width-1)/2.0),angle,1)
  154. print M
  155. dstImg = cv.warpAffine(srcImg, M, (width,height))
  156. return dstImg
  157. def rotaImg180(self, srcImg):
  158. dstImg = cv.flip(srcImg,0) #根据x轴翻转
  159. dstImg = cv.flip(dstImg,1) #根据y轴翻转
  160. return dstImg
  161. '''
  162. 根据传入的图片和高宽差参数,移动图片位置
  163. '''
  164. def transferImg(self, srcImg, dHeight, dWidth):
  165. height,width,color = srcImg.shape
  166. M = np.float32([[1,0,dWidth],[0,1,dHeight]])
  167. dstImg = cv.warpAffine(srcImg,M,(width,height))
  168. return dstImg
  169. '''
  170. 根据传入的图片mat和坐标点,计算灰阶中间值
  171. '''
  172. def calGrayMid(self, img, area):
  173. # cv.line(img,(area[0],area[1]),(area[2],area[3]),(0,255,0))
  174. # cv.imshow("img",img)
  175. # cv.waitKey(0)
  176. # cv.destroyAllWindows()
  177. dstArea = list(area)
  178. if area[0] + area[1] > area[2]+area[3]:
  179. dstArea[0] = area[2]
  180. dstArea[1] = area[3]
  181. dstArea[2] = area[0]
  182. dstArea[3] = area[1]
  183. dstImg = cutImage(img, dstArea)
  184. # print "ImageUtil.calGrayAvg: dstImg:",dstImg
  185. return (np.max(dstImg) + np.min(dstImg))/2
  186. '''
  187. 根据传入的图片mat和坐标点,计算灰阶平均值
  188. '''
  189. def calGrayAvg(self, img, area):
  190. # cv.line(img,(area[0],area[1]),(area[2],area[3]),(0,255,0))
  191. # cv.imshow("img",img)
  192. # cv.waitKey(0)
  193. # cv.destroyAllWindows()
  194. dstArea = list(area)
  195. if area[0] + area[1] > area[2]+area[3]:
  196. dstArea[0] = area[2]
  197. dstArea[1] = area[3]
  198. dstArea[2] = area[0]
  199. dstArea[3] = area[1]
  200. dstImg = cutImage(img, dstArea)
  201. # print "ImageUtil.calGrayAvg: dstImg:",dstImg
  202. return np.average(dstImg)