#-*- coding:utf-8 -*- import sys reload(sys) sys.setdefaultencoding('utf-8') from PIL import Image from PIL import ImageChops from PIL import ImageDraw from picture import PreImageJudge from picture.DoubleImage import DoubleImage from picture import CrossColor from picture import RGB from picture.feature_detect import * from ssat_sdk.picture.color_space import * from ssat_sdk.picture.pq_detect import PQDetect import ssat_sdk.picture.image_util import cv2 as cv import numpy as np ''' 用于向脚本提供图片、图像内容处理接口,提供图像检测接口、图像比对接口 ''' class ImageCMP(): def __init__(self): print "Init Image Compare tool" self.featureDetect = FeatureDetect() self.CIECaculator = CIEluvCaculator() self.doubleImg = DoubleImage() self.pq = PQDetect() def getBlendImageCount(self, img): print "getBlendImageCount,img1.size", img.size, ";format:", img.format, ";model:", img.mode imgL = img.convert("L") pixSum = imgL.histogram() nonZeroCount = 0 for i in range(pixSum.__len__()): if (pixSum[i] <> 0): nonZeroCount = nonZeroCount + 1 print "getImageLArr,nonZeroCount=", nonZeroCount print pixSum return nonZeroCount def checkLikePic(self, im1, im2): im3 = ImageChops.invert(im2) im4 = Image.blend(im1, im3, 0.5) return self.getBlendImageCount(im4) ''' 参数,传入两张需要比对的图片的地址 返回值:True代表图片一致,False代表图片不一致 ''' def cmpPicTotal(self, picPath1, picPath2, threshold=20, expDotRate=0.001): return self.doubleImg.cmpPicTotal(picPath1,picPath2, threshold, expDotRate) ''' 参数,传入两张需要比对的图片的对象 返回值:True代表图片一致,False代表图片不一致 ''' def cmpImgTotal(self, img1, img2, threshold=20, expDotRate=0.001): print "cmpImgTotal,",img1.shape, img2.shape return self.doubleImg.cmpImgTotal(img1, img2, threshold, expDotRate) ''' # 参数,传入两张需要比对的图片的地址,采用颜色空间LUV进行颜色判断。 :param picPath1:第一张图片路径 :param picPath2:第二张图片路径 :param lineStd:luv差距值,相似度的阈值 :return 判断颜色是否一样,True 或者False ''' def cmpPicLuv(self, picPath1, picPath2, lineStd = 5): img1 = cv.imread(picPath1) luv1 = self.CIECaculator.getAverageLUV(cv.cvtColor(img1, cv.COLOR_BGR2LUV)) img2 = cv.imread(picPath2) luv2 = self.CIECaculator.getAverageLUV(cv.cvtColor(img2, cv.COLOR_BGR2LUV)) L, U, diff = self.CIECaculator.getDiffLevel(luv1,luv2) print L, U, diff if diff <= lineStd: return True else: return False ''' #裁剪原图片文件的area区域,并保存到destPath文件中 :param srcPic:图片文件路径 :param destPath:裁剪图片保存路径 :param area:(start_pointX,start_pointY,end_pointX, end_pointY). 原点:左上角,高为y轴,宽为x轴 :return True/False ''' def saveCropPic(self,srcPic, destPath, area): return image_util.saveCropPic(srcPic, destPath, area) ''' #解决image的area区域,并保存到destPath文件中。srcImage是PIL里的Image对象。 :param srcImg:Opencv图片对象 :param area:(start_pointX,start_pointY,end_pointX, end_pointY). 原点:左上角,高为y轴,宽为x轴 :return True/False ''' def saveCropImage(self, srcImg, destPath, area): return image_util.saveCropImg(srcImg, destPath, area) ''' 裁剪非选中区域,返回image对象列表 :param srcPic:图片文件路径 :param area:选中区域 :return 列表:OpenCV图像对象,BGR颜色空间 ''' def saveRetPic(self,srcPic, area): return image_util.saveRetCropPic(srcPic,area) """ 参数: cv_img:数组,OpenCV常用的图像3维数组。例如:imread返回的值 area:元组,被检测的图片区域,例如:(start_pointX,start_pointY,end_pointX, end_pointY) targetBGR:元组,应该达成的BGR数值。例如:(Blue,Green,Red) 返回值: True:代表直线与目标BGR值符合。 False:代表直线与目标BGR值不符合。 """ def checkLineByImg(self, cv_img, area, targetBGR): if cv_img == None: return False for x in range(area[0],area[2]): for y in range(area[1], area[3]): print x,y, cv_img[x,y] if (abs(cv_img[x,y][0] - targetBGR[0]) > 20) \ or (abs(cv_img[x,y][1] - targetBGR[1]) > 20) \ or (abs(cv_img[x,y][2] <> targetBGR[3]) > 20): return False return True """ 参数: picpath 字符串,图片文件的路径 area:元组,被检测的图片区域,例如:(start_pointX,start_pointY,end_pointX, end_pointY) targetBGR:元组,应该达成的BGR数值。例如:(Blue,Green,Red) 返回值: True:代表直线与目标BGR值符合。 False:代表直线与目标BGR值不符合。 """ def checkLineByPath(self, picpath, area, targetBGR): areaDXRY = self.coordinateRXDY2DXRY(area) return self.checkLineByImg(cv.imread(picpath), areaDXRY, targetBGR) def coordinateRXDY2DXRY(self, areaRXDY): areaDXRY = [] areaDXRY.append(areaRXDY[1]) areaDXRY.append(areaRXDY[0]) areaDXRY.append(areaRXDY[3]) areaDXRY.append(areaRXDY[2]) return areaDXRY def isDoubleImage(self,std_picpath,test_picpath): return not (DoubleImage.cmpPicTotal(std_picpath,test_picpath)) ''' ::接口异常 ''' def isCrossColor(self,picpath): return not (CrossColor.cmpPicTotal(picpath)) ''' 判断一张图片是否是纯黑图片。 :param picpath:需要判断的图片路径 :param grayTH : 黑色判断的灰阶阈值 :param splitCount: 图片拆分的行列次数 :param expTh:黑色计算的容错区域比例。 ''' def isBlack(self,picpath, black_th=15,splitCount=10, expTh = 0.01): #print "pic_tool.isBlack, picpath=", picpath rgb = RGB.RGBColor() img = cv.imread(picpath) return rgb.isBlack(img, black_th, splitCount, expTh) ''' 获取区域的最大RGB值 :param picpath:图片路径。 area:图片区域坐标。 ''' def getMaxRGB(self,picpath,area): return PreImageJudge.getMaxRGB(picpath,area) ''' 获取区域的BGR平均值 :param picpath:图片路径。 area:图片区域坐标。 ''' def getAverageRGB(self,picpath,area): return PreImageJudge.getAverageRGB(picpath,area) ''' 获取区域的平均灰阶值 :param picpath:图片路径。 area:图片区域坐标。 ''' def getAvgGray(self, picpath, area): return self.CIECaculator.getAvgGray(picpath, area) ''' 返回图片指定坐标的BGR颜色值 :param img: cv.imread()返回的图片对象 :param point坐标:(高,宽) :return BGR颜色值:(blue,green,red) ''' def getDotBGR(self,img, point): return img[point[0], point[1]] ''' 检测图像是否有马赛克 ''' def hasMosaic(self,std_pic,test_pic): return PreImageJudge.hasMosaic(std_pic,test_pic) ''' ::接口废弃 ''' def cmpPicWithRGB(self,std_pic,test_pic): return RGB.cmpPicWithRGB(std_pic,test_pic) ''' 用途:加载一张图片文件,获取指定长度的直线。可以指定图片区域,获取指定区域的直线 :param file:文件路径 :param lineMinLen:直线最短界限 :param lineMaxLen:直线最长界限 :return line数组:[[x1,y1,x2,y2],[...],...] ''' def getLinesByFile(self, file, lineMinLen=20, lineMaxLen=1000, ableArea=None, threshold1=50, threshold2=100, apertureSize=5): return self.featureDetect.getLinesByFile(file,lineMinLen,lineMaxLen,ableArea,threshold1,threshold2,apertureSize) ''' 用途:传入OpenCV读取的image图片对象,获取指定长度的直线。可以指定图片区域,获取指定区域的直线 :param file:文件路径 :param lineMinLen:直线最短界限 :param lineMaxLen:直线最长界限 :return line数组:[[x1,y1,x2,y2],[...],...] ''' def getLinesByImg(self, img, lineMinLen=20, lineMaxLen=1000, ableArea=None, threshold1=50, threshold2=100, apertureSize=5): return self.featureDetect.getLines(img,lineMinLen,lineMaxLen,ableArea,threshold1,threshold2,apertureSize) ''' 读取传入的图片路径,加载图片。 检测中心区域外的四周颜色是否为纯色图片,且四周纯色一致。 :param picPath:图片路径 :rate :四周在宽、高上的比例。 :return :检测结果。Ture/False ''' def checkAroundSSColor(self, picPath, rate=0.2): srcImg = cv.imread(picPath) height,width,color = srcImg.shape # print "checkAroundSSColor,height,width,color:",height,width,color centerArea = [int(width*rate), int(height*rate), int(width*(1-rate)), int(height*(1-rate))] imgList = image_util.saveRetCropImg(srcImg, centerArea) for index in range(1,imgList.__len__()): prevImg = imgList[index-1] currentImg = imgList[index] prevSingle = self.isSingleColor(prevImg) currentSingle = self.isSingleColor(prevImg) isSimilar = self.rgbColor.isColorSimilar(prevSingle[1],currentSingle[1]) # print "checkAroundSSColor:",prevSingle,currentSingle,isSimilar self.rgbColor = None if prevSingle[0] and currentSingle[0] and isSimilar: continue else: return False return True ''' 比较bgr1和bgr2颜色是否一样 ''' def isColorSimilar(self, bgr1, bgr2): rgbColor = RGB.RGBColor() return rgbColor.isColorSimilar(bgr1,bgr2) ''' 判断图片对象是否为纯色图片 :param img: OpenCV的mat对象 :return 检测结果:[Ture/False, [BGR平均值]] ''' def isSingleColor(self, img): self.rgbColor = RGB.RGBColor() return self.rgbColor.isSingleColor(img) ''' 根据传入的图片路径,计算图片色温.图片必须是单色图片 :param picPath,图片路径 ''' def calculateCCT(self, picPath): return self.pq.calculateCCT(picPath) ''' 根据传入的图片路径,计算图片清晰度。 :param picPath,图片路径 ''' def detectSharpness(self, picPath): return self.pq.detSharpTenengrad(picPath) if __name__ == "__main__": imgCmp = ImageCMP() #bled = r"D:\TST\test1\blend.jpg" #diffPath = r"D:\TST\test1\diff.jpg" #pic1 = r"D:\TST\test1\contrast-10.jpg" #pic2 = r"D:\TST\test1\brightness+10.jpg" #imgCmp.cmpPicTotal(pic1,pic2) #pic3= r"D:\TST\image\65-601.jpg" #pic4= r"D:\TST\image\65-603.jpg" #imgCmp.cmpPicTotal(pic3,pic4) picPath = r"D:\1.png" imgCmp.calulateCCT(picPath) # mat = np.array(cv.imread(picPath)) # print mat # PreImageJudge.getMaxRGB(picPath,(0,0,100,200)) # cv.imshow("test",np.array(mat)) # rxdyArea = imgCmp.coordinateRXDY2DXRY([0,0,200,300]) # mat5 = mat[rxdyArea[0]:rxdyArea[2],rxdyArea[1]:rxdyArea[3]] # cv.imshow("test5",np.array(mat5)) # cv.waitKey(0) # cv.destroyAllWindows() # print imgCmp.checkLineByPath(mat5, (507,200,798,200), (255,0,0))