# -*- coding:utf-8 -*- import os, sys, time import inspect import cv2 as cv import numpy as np from ssat_sdk.utils import LoggingUtil pyFileName = os.path.split(__file__)[-1] def get_current_function_name(): return inspect.stack()[1][3] ''' 按照坐标系调整区域数值 :param areaRXDY:二维区域。坐标系:x轴:水平向右,y轴:纵向向下 :return areaDXRY:二维区域。坐标系:x轴:纵向向下,y轴:水平向右 ''' def coordinateRXDY2DXRY(areaRXDY): areaDXRY = [] areaDXRY.append(areaRXDY[1]) areaDXRY.append(areaRXDY[0]) areaDXRY.append(areaRXDY[3]) areaDXRY.append(areaRXDY[2]) return areaDXRY ''' 截取图片区域。 :param area:二维区域。area按照常规x,y坐标描述。示例:[x1,y1,x2,y2]. 点(x1,y1)为矩形左上角,点(x2,y2)为矩形右下角。 ''' def cutMat(srcimg, area): try: mat_area = coordinateRXDY2DXRY(area) # print "cutMat:mat_area:", mat_area imgArr = np.array(srcimg) retMat = imgArr[int(mat_area[0]):int(mat_area[2]),int(mat_area[1]):int(mat_area[3])] del imgArr return retMat except Exception, e: LoggingUtil.getDebugLogger().info(pyFileName, "image_util", get_current_function_name(), 'ERROR:截图异常:'+str(e)) return None ''' # 描述:裁剪图片,返回指定裁剪区域的图片; # 参数: # srcimg:opencv.imread打开的对象。 # area: 要裁剪的区域,示例:[x1,y1,x2,y2]. 点(x1,y1)为矩形左上角,点(x2,y2)为矩形右下角。 # # 返回:成功返回裁剪区域的图片对象,否则返回None # # 注意:相对cutMat来说,少一步坐标转换。 # ''' def cutImage(srcimg, area): try: return np.array(srcimg[area[1]:area[3]+1, area[0]:area[2]+1]) except Exception,e: LoggingUtil.getDebugLogger().info(pyFileName, "image_util", get_current_function_name(), 'ERROR:裁剪图片异常:'+str(e)) return None ''' # 描述:裁剪图片,返回指定裁剪区域的图片; # 参数: # imgPath:图片路径 # area: 要裁剪的区域,示例:[x1,y1,x2,y2]. 点(x1,y1)为矩形左上角,点(x2,y2)为矩形右下角。 # # 返回:成功返回裁剪区域的图片对象,否则返回None # # 注意:相对cutMat来说,少一步坐标转换。 # ''' def cutImageByPath(imgPath, area): srcimg = cv.imread(imgPath) try: dstImg = cutImage(srcimg, area) del srcimg return dstImg except Exception,e: LoggingUtil.getDebugLogger().info(pyFileName, "image_util", get_current_function_name(), 'ERROR:裁剪图片异常:'+str(e)) return None def saveCropImg(srcImg, destPic, area): if srcImg is None: LoggingUtil.getDebugLogger().info(pyFileName, "image_util", get_current_function_name(), 'SDK:打开图像返回空对象,文件可能不存在或无权限打开') return False if len(area) != 4: LoggingUtil.getDebugLogger().info(pyFileName, "image_util", get_current_function_name(), 'SDK:给定的区域坐标无效:'+str(area)) return False destImg = cutMat(srcImg, area) if destImg is None: LoggingUtil.getDebugLogger().info(pyFileName, "image_util", get_current_function_name(), 'SDK:截图失败:') return False cv.imwrite(destPic,destImg) del destImg return True def saveCropPic(srcPic, destPic, area): srcImg = cv.imread(srcPic) ret = saveCropImg(srcImg, destPic, area) del srcImg return ret def cutImgWithRate(srcImg, destPic, rateArea): height, width, dim = srcImg.shape print "srcImg: height, width:", height, width, rateArea dest_x1 = int(width * rateArea[0]) dest_x2 = int(width * rateArea[2]) dest_y1 = int(height * rateArea[1]) dest_y2 = int(height * rateArea[3]) print "dest: dest_x1,dest_y1, dest_x2, dest_y2:", dest_x1,dest_y1, dest_x2, dest_y2 destImg = cutMat(srcImg, (dest_x1,dest_y1, dest_x2, dest_y2)) cv.imwrite(destPic, destImg) del destImg ''' 根据比例裁剪图片,并保存裁剪结果到指定文件中 ''' def cutPicWithRate(srcPic, destPic, rateArea): srcImg = cv.imread(srcPic) cutImgWithRate(srcImg, destPic, rateArea) del srcImg ''' 截取选中区域以外的图片 ''' def saveRetCropPic(srcPic, area): srcImg = cv.imread(srcPic) imgList = saveRetCropImg(srcImg, area) del srcImg return imgList def saveRetCropImg(srcImg, area): # print "saveRetCropImg,area:",area height,width,chNum = srcImg.shape area1 = [0,0,area[0], height] area2 = [area[0],0,area[2], area[1]] area3 = [area[0], area[3],area[2], height] area4 = [area[2],0,width, height] rectList = [] addRect2List(rectList, area1) addRect2List(rectList, area2) addRect2List(rectList, area3) addRect2List(rectList, area4) imgList = [] for rect in rectList: img = cutMat(srcImg, rect) imgList.append(img) return imgList ''' 根据设定的灰阶阈值,保存一张新图片,并返回img对象。 原图像是BGR模式 ''' def saveThresholdPicImg(srcImg,threshLow,threshTop, thresholdType): # print u"转成灰阶图;" img_gray = cv.cvtColor(srcImg, cv.COLOR_BGR2GRAY) # print u"转成二值化;" ret, img_threshold = cv.threshold(img_gray, threshLow, threshTop, thresholdType) del img_gray return img_threshold ''' 检测rect是否正确,正确才添加到rectList ''' def addRect2List(rectList, rect): # print "addRect2List,rect:",rect if (rect[0] <> rect[2]) and (rect[1] <> rect[3]): rectList.append(rect) def caculateLinLen(line): dx = abs(line[0] - line[2]) dy = abs(line[1]-line[3]) # print "caculateLinLen:",dx,dy lineLen = np.sqrt(np.square(dx) + np.square(dy)) return lineLen class ImageUtil(): def __init__(self): pass ''' 根据传入的图像对象,逆时针旋转角度 ''' def rotaImg(self, srcImg, angle): height, width, color = srcImg.shape M = cv.getRotationMatrix2D(((height-1)/2.0,(width-1)/2.0),angle,1) print M dstImg = cv.warpAffine(srcImg, M, (width,height)) return dstImg def rotaImg180(self, srcImg): dstImg = cv.flip(srcImg,0) #根据x轴翻转 dstImg = cv.flip(dstImg,1) #根据y轴翻转 return dstImg ''' 根据传入的图片和高宽差参数,移动图片位置 ''' def transferImg(self, srcImg, dHeight, dWidth): height,width,color = srcImg.shape M = np.float32([[1,0,dWidth],[0,1,dHeight]]) dstImg = cv.warpAffine(srcImg,M,(width,height)) return dstImg ''' 根据传入的图片mat和坐标点,计算灰阶中间值 ''' def calGrayMid(self, img, area): # cv.line(img,(area[0],area[1]),(area[2],area[3]),(0,255,0)) # cv.imshow("img",img) # cv.waitKey(0) # cv.destroyAllWindows() dstArea = list(area) if area[0] + area[1] > area[2]+area[3]: dstArea[0] = area[2] dstArea[1] = area[3] dstArea[2] = area[0] dstArea[3] = area[1] dstImg = cutImage(img, dstArea) # print "ImageUtil.calGrayAvg: dstImg:",dstImg return (np.max(dstImg) + np.min(dstImg))/2 ''' 根据传入的图片mat和坐标点,计算灰阶平均值 ''' def calGrayAvg(self, img, area): # cv.line(img,(area[0],area[1]),(area[2],area[3]),(0,255,0)) # cv.imshow("img",img) # cv.waitKey(0) # cv.destroyAllWindows() dstArea = list(area) if area[0] + area[1] > area[2]+area[3]: dstArea[0] = area[2] dstArea[1] = area[3] dstArea[2] = area[0] dstArea[3] = area[1] dstImg = cutImage(img, dstArea) # print "ImageUtil.calGrayAvg: dstImg:",dstImg return np.average(dstImg)