pic_tool.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. #-*- coding:utf-8 -*-
  2. import sys
  3. reload(sys)
  4. sys.setdefaultencoding('utf-8')
  5. from PIL import Image
  6. from PIL import ImageChops
  7. from PIL import ImageDraw
  8. from picture import PreImageJudge
  9. from picture.DoubleImage import DoubleImage
  10. from picture import CrossColor
  11. from picture import RGB
  12. from picture.feature_detect import *
  13. from ssat_sdk.picture.color_space import *
  14. from ssat_sdk.picture.pq_detect import PQDetect
  15. import ssat_sdk.picture.image_util
  16. import cv2 as cv
  17. import numpy as np
  18. '''
  19. 用于向脚本提供图片、图像内容处理接口,提供图像检测接口、图像比对接口
  20. '''
  21. class ImageCMP():
  22. def __init__(self):
  23. print "Init Image Compare tool"
  24. self.featureDetect = FeatureDetect()
  25. self.CIECaculator = CIEluvCaculator()
  26. self.doubleImg = DoubleImage()
  27. self.pq = PQDetect()
  28. def getBlendImageCount(self, img):
  29. print "getBlendImageCount,img1.size", img.size, ";format:", img.format, ";model:", img.mode
  30. imgL = img.convert("L")
  31. pixSum = imgL.histogram()
  32. nonZeroCount = 0
  33. for i in range(pixSum.__len__()):
  34. if (pixSum[i] <> 0):
  35. nonZeroCount = nonZeroCount + 1
  36. print "getImageLArr,nonZeroCount=", nonZeroCount
  37. print pixSum
  38. return nonZeroCount
  39. def checkLikePic(self, im1, im2):
  40. im3 = ImageChops.invert(im2)
  41. im4 = Image.blend(im1, im3, 0.5)
  42. return self.getBlendImageCount(im4)
  43. '''
  44. 参数,传入两张需要比对的图片的地址
  45. 返回值:True代表图片一致,False代表图片不一致
  46. '''
  47. def cmpPicTotal(self, picPath1, picPath2, threshold=20, expDotRate=0.001):
  48. return self.doubleImg.cmpPicTotal(picPath1,picPath2, threshold, expDotRate)
  49. '''
  50. 参数,传入两张需要比对的图片的对象
  51. 返回值:True代表图片一致,False代表图片不一致
  52. '''
  53. def cmpImgTotal(self, img1, img2, threshold=20, expDotRate=0.001):
  54. print "cmpImgTotal,",img1.shape, img2.shape
  55. return self.doubleImg.cmpImgTotal(img1, img2, threshold, expDotRate)
  56. '''
  57. # 参数,传入两张需要比对的图片的地址,采用颜色空间LUV进行颜色判断。
  58. :param picPath1:第一张图片路径
  59. :param picPath2:第二张图片路径
  60. :param lineStd:luv差距值,相似度的阈值
  61. :return 判断颜色是否一样,True 或者False
  62. '''
  63. def cmpPicLuv(self, picPath1, picPath2, lineStd = 5):
  64. img1 = cv.imread(picPath1)
  65. luv1 = self.CIECaculator.getAverageLUV(cv.cvtColor(img1, cv.COLOR_BGR2LUV))
  66. img2 = cv.imread(picPath2)
  67. luv2 = self.CIECaculator.getAverageLUV(cv.cvtColor(img2, cv.COLOR_BGR2LUV))
  68. L, U, diff = self.CIECaculator.getDiffLevel(luv1,luv2)
  69. print L, U, diff
  70. if diff <= lineStd:
  71. return True
  72. else:
  73. return False
  74. '''
  75. #裁剪原图片文件的area区域,并保存到destPath文件中
  76. :param srcPic:图片文件路径
  77. :param destPath:裁剪图片保存路径
  78. :param area:(start_pointX,start_pointY,end_pointX, end_pointY). 原点:左上角,高为y轴,宽为x轴
  79. :return True/False
  80. '''
  81. def saveCropPic(self,srcPic, destPath, area):
  82. return image_util.saveCropPic(srcPic, destPath, area)
  83. '''
  84. #解决image的area区域,并保存到destPath文件中。srcImage是PIL里的Image对象。
  85. :param srcImg:Opencv图片对象
  86. :param area:(start_pointX,start_pointY,end_pointX, end_pointY). 原点:左上角,高为y轴,宽为x轴
  87. :return True/False
  88. '''
  89. def saveCropImage(self, srcImg, destPath, area):
  90. return image_util.saveCropImg(srcImg, destPath, area)
  91. '''
  92. 裁剪非选中区域,返回image对象列表
  93. :param srcPic:图片文件路径
  94. :param area:选中区域
  95. :return 列表:OpenCV图像对象,BGR颜色空间
  96. '''
  97. def saveRetPic(self,srcPic, area):
  98. return image_util.saveRetCropPic(srcPic,area)
  99. """
  100. 参数:
  101. cv_img:数组,OpenCV常用的图像3维数组。例如:imread返回的值
  102. area:元组,被检测的图片区域,例如:(start_pointX,start_pointY,end_pointX, end_pointY)
  103. targetBGR:元组,应该达成的BGR数值。例如:(Blue,Green,Red)
  104. 返回值:
  105. True:代表直线与目标BGR值符合。
  106. False:代表直线与目标BGR值不符合。
  107. """
  108. def checkLineByImg(self, cv_img, area, targetBGR):
  109. if cv_img == None:
  110. return False
  111. for x in range(area[0],area[2]):
  112. for y in range(area[1], area[3]):
  113. print x,y, cv_img[x,y]
  114. if (abs(cv_img[x,y][0] - targetBGR[0]) > 20) \
  115. or (abs(cv_img[x,y][1] - targetBGR[1]) > 20) \
  116. or (abs(cv_img[x,y][2] <> targetBGR[3]) > 20):
  117. return False
  118. return True
  119. """
  120. 参数:
  121. picpath 字符串,图片文件的路径
  122. area:元组,被检测的图片区域,例如:(start_pointX,start_pointY,end_pointX, end_pointY)
  123. targetBGR:元组,应该达成的BGR数值。例如:(Blue,Green,Red)
  124. 返回值:
  125. True:代表直线与目标BGR值符合。
  126. False:代表直线与目标BGR值不符合。
  127. """
  128. def checkLineByPath(self, picpath, area, targetBGR):
  129. areaDXRY = self.coordinateRXDY2DXRY(area)
  130. return self.checkLineByImg(cv.imread(picpath), areaDXRY, targetBGR)
  131. def coordinateRXDY2DXRY(self, areaRXDY):
  132. areaDXRY = []
  133. areaDXRY.append(areaRXDY[1])
  134. areaDXRY.append(areaRXDY[0])
  135. areaDXRY.append(areaRXDY[3])
  136. areaDXRY.append(areaRXDY[2])
  137. return areaDXRY
  138. def isDoubleImage(self,std_picpath,test_picpath):
  139. return not (DoubleImage.cmpPicTotal(std_picpath,test_picpath))
  140. '''
  141. ::接口异常
  142. '''
  143. def isCrossColor(self,picpath):
  144. return not (CrossColor.cmpPicTotal(picpath))
  145. '''
  146. 判断一张图片是否是纯黑图片。
  147. :param picpath:需要判断的图片路径
  148. :param grayTH : 黑色判断的灰阶阈值
  149. :param splitCount: 图片拆分的行列次数
  150. :param expTh:黑色计算的容错区域比例。
  151. '''
  152. def isBlack(self,picpath, black_th=15,splitCount=10, expTh = 0.01):
  153. #print "pic_tool.isBlack, picpath=", picpath
  154. rgb = RGB.RGBColor()
  155. img = cv.imread(picpath)
  156. return rgb.isBlack(img, black_th, splitCount, expTh)
  157. '''
  158. 获取区域的最大RGB值
  159. :param picpath:图片路径。 area:图片区域坐标。
  160. '''
  161. def getMaxRGB(self,picpath,area):
  162. return PreImageJudge.getMaxRGB(picpath,area)
  163. '''
  164. 获取区域的BGR平均值
  165. :param picpath:图片路径。 area:图片区域坐标。
  166. '''
  167. def getAverageRGB(self,picpath,area):
  168. return PreImageJudge.getAverageRGB(picpath,area)
  169. '''
  170. 获取区域的平均灰阶值
  171. :param picpath:图片路径。 area:图片区域坐标。
  172. '''
  173. def getAvgGray(self, picpath, area):
  174. return self.CIECaculator.getAvgGray(picpath, area)
  175. '''
  176. 返回图片指定坐标的BGR颜色值
  177. :param img: cv.imread()返回的图片对象
  178. :param point坐标:(高,宽)
  179. :return BGR颜色值:(blue,green,red)
  180. '''
  181. def getDotBGR(self,img, point):
  182. return img[point[0], point[1]]
  183. '''
  184. 检测图像是否有马赛克
  185. '''
  186. def hasMosaic(self,std_pic,test_pic):
  187. return PreImageJudge.hasMosaic(std_pic,test_pic)
  188. '''
  189. ::接口废弃
  190. '''
  191. def cmpPicWithRGB(self,std_pic,test_pic):
  192. return RGB.cmpPicWithRGB(std_pic,test_pic)
  193. '''
  194. 用途:加载一张图片文件,获取指定长度的直线。可以指定图片区域,获取指定区域的直线
  195. :param file:文件路径
  196. :param lineMinLen:直线最短界限
  197. :param lineMaxLen:直线最长界限
  198. :return line数组:[[x1,y1,x2,y2],[...],...]
  199. '''
  200. def getLinesByFile(self, file, lineMinLen=20, lineMaxLen=1000, ableArea=None, threshold1=50, threshold2=100,
  201. apertureSize=5):
  202. return self.featureDetect.getLinesByFile(file,lineMinLen,lineMaxLen,ableArea,threshold1,threshold2,apertureSize)
  203. '''
  204. 用途:传入OpenCV读取的image图片对象,获取指定长度的直线。可以指定图片区域,获取指定区域的直线
  205. :param file:文件路径
  206. :param lineMinLen:直线最短界限
  207. :param lineMaxLen:直线最长界限
  208. :return line数组:[[x1,y1,x2,y2],[...],...]
  209. '''
  210. def getLinesByImg(self, img, lineMinLen=20, lineMaxLen=1000, ableArea=None, threshold1=50, threshold2=100,
  211. apertureSize=5):
  212. return self.featureDetect.getLines(img,lineMinLen,lineMaxLen,ableArea,threshold1,threshold2,apertureSize)
  213. '''
  214. 读取传入的图片路径,加载图片。
  215. 检测中心区域外的四周颜色是否为纯色图片,且四周纯色一致。
  216. :param picPath:图片路径
  217. :rate :四周在宽、高上的比例。
  218. :return :检测结果。Ture/False
  219. '''
  220. def checkAroundSSColor(self, picPath, rate=0.2):
  221. srcImg = cv.imread(picPath)
  222. height,width,color = srcImg.shape
  223. # print "checkAroundSSColor,height,width,color:",height,width,color
  224. centerArea = [int(width*rate), int(height*rate), int(width*(1-rate)), int(height*(1-rate))]
  225. imgList = image_util.saveRetCropImg(srcImg, centerArea)
  226. for index in range(1,imgList.__len__()):
  227. prevImg = imgList[index-1]
  228. currentImg = imgList[index]
  229. prevSingle = self.isSingleColor(prevImg)
  230. currentSingle = self.isSingleColor(prevImg)
  231. isSimilar = self.rgbColor.isColorSimilar(prevSingle[1],currentSingle[1])
  232. # print "checkAroundSSColor:",prevSingle,currentSingle,isSimilar
  233. self.rgbColor = None
  234. if prevSingle[0] and currentSingle[0] and isSimilar:
  235. continue
  236. else:
  237. return False
  238. return True
  239. '''
  240. 比较bgr1和bgr2颜色是否一样
  241. '''
  242. def isColorSimilar(self, bgr1, bgr2):
  243. rgbColor = RGB.RGBColor()
  244. return rgbColor.isColorSimilar(bgr1,bgr2)
  245. '''
  246. 判断图片对象是否为纯色图片
  247. :param img: OpenCV的mat对象
  248. :return 检测结果:[Ture/False, [BGR平均值]]
  249. '''
  250. def isSingleColor(self, img):
  251. self.rgbColor = RGB.RGBColor()
  252. return self.rgbColor.isSingleColor(img)
  253. '''
  254. 根据传入的图片路径,计算图片色温.图片必须是单色图片
  255. :param picPath,图片路径
  256. '''
  257. def calculateCCT(self, picPath):
  258. return self.pq.calculateCCT(picPath)
  259. '''
  260. 根据传入的图片路径,计算图片清晰度。
  261. :param picPath,图片路径
  262. '''
  263. def detectSharpness(self, picPath):
  264. return self.pq.detSharpTenengrad(picPath)
  265. if __name__ == "__main__":
  266. imgCmp = ImageCMP()
  267. #bled = r"D:\TST\test1\blend.jpg"
  268. #diffPath = r"D:\TST\test1\diff.jpg"
  269. #pic1 = r"D:\TST\test1\contrast-10.jpg"
  270. #pic2 = r"D:\TST\test1\brightness+10.jpg"
  271. #imgCmp.cmpPicTotal(pic1,pic2)
  272. #pic3= r"D:\TST\image\65-601.jpg"
  273. #pic4= r"D:\TST\image\65-603.jpg"
  274. #imgCmp.cmpPicTotal(pic3,pic4)
  275. picPath = r"D:\1.png"
  276. imgCmp.calulateCCT(picPath)
  277. # mat = np.array(cv.imread(picPath))
  278. # print mat
  279. # PreImageJudge.getMaxRGB(picPath,(0,0,100,200))
  280. # cv.imshow("test",np.array(mat))
  281. # rxdyArea = imgCmp.coordinateRXDY2DXRY([0,0,200,300])
  282. # mat5 = mat[rxdyArea[0]:rxdyArea[2],rxdyArea[1]:rxdyArea[3]]
  283. # cv.imshow("test5",np.array(mat5))
  284. # cv.waitKey(0)
  285. # cv.destroyAllWindows()
  286. # print imgCmp.checkLineByPath(mat5, (507,200,798,200), (255,0,0))