image_util.py 7.8 KB

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