123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- #-*- 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(currentImg)
- 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()
- picStandard = r"E:\0year2020\pic\standard.jpg"
- picDynamic = r"E:\0year2020\pic\dynamic.jpg"
- picMovie = r"E:\0year2020\pic\movie.jpg"
- cctM = imgCmp.calculateCCT(picMovie)
- cctS = imgCmp.calculateCCT(picStandard)
- cctD = imgCmp.calculateCCT(picDynamic)
-
- print "cctM", cctM
- print "cctS",cctS
- print "cctD", cctD
- #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"
- # 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))
|