图像基础10 比较图片是否一样

方法一 使用cv2 矩阵减subtract

  1. 两个图片完全一样时返回值为true
  2. 如果把一个图片转了格式,则会被为不一样
import cv2
import numpy as np


file2 = "1.jpg"
file1 = "1.png"
 
image1 = cv2.imread(file1)
image2 = cv2.imread(file2)
difference = cv2.subtract(image1, image2)
result = not np.any(difference) #if difference is all zeros it will return False
 
if result is True:
     print("两张图片一样")
else:
     cv2.imwrite("result.jpg", difference)
     print ("两张图片不一样")

测试一个jpg图片和转成png进行比较,两张图片不一样

方法二 按像素计算差异数

# -*- coding: utf-8 -*-
#!/usr/bin/python
import numpy as np 
import cv2 
global n 
n = 0 
img1 = cv2.imread('1.jpg', cv2.IMREAD_GRAYSCALE) 
img2 = cv2.imread('1.png', cv2.IMREAD_GRAYSCALE) 
height, width = img1.shape 
for line in range(height): 
    for pixel in range(width): 
        if img1[line][pixel] != img2[line][pixel]: 
            n = n + 1 
print (n)

方法三 计算灰度图hash值

  • 不同类型的图片也可以比较
# -*- coding: utf-8 -*-
import pytesseract  
from pytesseract import *  
from PIL import Image,ImageEnhance,ImageFilter  
import os  
import fnmatch  
import re,time  
import urllib, random  
   
def getGray(image_file):  
   tmpls=[]  
   for h in range(0,  image_file.size[1]):#h  
      for w in range(0, image_file.size[0]):#w  
         tmpls.append( image_file.getpixel((w,h))  )  
            
   return tmpls  
   
def getAvg(ls):#获取平均灰度值  
   return sum(ls)/len(ls)  
   
def getMH(a,b):#比较100个字符有几个字符相同  
   dist = 0;  
   for i in range(0,len(a)):  
      if a[i]==b[i]:  
         dist=dist+1  
   return dist  
   
def getImgHash(fne):  
   image_file = Image.open(fne) # 打开  
   image_file=image_file.resize((12, 12))#重置图片大小我12px X 12px  
   image_file=image_file.convert("L")#转256灰度图  
   Grayls=getGray(image_file)#灰度集合  
   avg=getAvg(Grayls)#灰度平均值  
   bitls=''#接收获取0或1  
   #除去变宽1px遍历像素  
   for h in range(1,  image_file.size[1]-1):#h  
      for w in range(1, image_file.size[0]-1):#w  
         if image_file.getpixel((w,h))>=avg:#像素的值比较平均值 大于记为1 小于记为0  
            bitls=bitls+'1'  
         else:  
            bitls=bitls+'0'  
   return bitls
   
a=getImgHash("1.jpg")#图片地址自行替换  
b=getImgHash("1.png")  
compare=getMH(a,b)  
print (u'相似度'+str(compare)+'%')  

计算一个jpg和转成png的图片比较相似度为100%

方法四 灰度直方图作为相似比较

图像识别中,常用的特征:

  • 颜色特征(最常用)
  • 纹理特征
  • 形状特征
  • 空间关系特征

颜色特征分为:

  • 直方图
  • 颜色集
  • 颜色矩
  • 聚合向量
  • 相关图
# -*- coding: utf-8 -*-
#!/usr/bin/python
  
import cv2 
import numpy as np 
from matplotlib import pyplot as plt 
  
# 最简单的以灰度直方图作为相似比较的实现 
def classify_gray_hist(image1,image2,size = (256,256)): 
    # 先计算直方图 
    # 几个参数必须用方括号括起来 
    # 这里直接用灰度图计算直方图,所以是使用第一个通道, 
    # 也可以进行通道分离后,得到多个通道的直方图 
    # bins 取为16 
    image1 = cv2.resize(image1,size) 
    image2 = cv2.resize(image2,size) 
    hist1 = cv2.calcHist([image1],[0],None,[256],[0.0,255.0]) 
    hist2 = cv2.calcHist([image2],[0],None,[256],[0.0,255.0]) 
    # 可以比较下直方图 
    plt.plot(range(256),hist1,'r') 
    plt.plot(range(256),hist2,'b') 
    #plt.show() 
    # 计算直方图的重合度 
    degree = 0
    for i in range(len(hist1)): 
        if hist1[i] != hist2[i]: 
            degree = degree + (1 - abs(hist1[i]-hist2[i])/max(hist1[i],hist2[i])) 
        else: 
            degree = degree + 1
    degree = degree/len(hist1) 
    return degree 
  
# 计算单通道的直方图的相似值 
def calculate(image1,image2): 
    hist1 = cv2.calcHist([image1],[0],None,[256],[0.0,255.0]) 
    hist2 = cv2.calcHist([image2],[0],None,[256],[0.0,255.0]) 
    # 计算直方图的重合度 
    degree = 0
    for i in range(len(hist1)): 
        if hist1[i] != hist2[i]: 
            degree = degree + (1 - abs(hist1[i]-hist2[i])/max(hist1[i],hist2[i])) 
        else: 
            degree = degree + 1
    degree = degree/len(hist1) 
    return degree
  
# 通过得到每个通道的直方图来计算相似度 
def classify_hist_with_split(image1,image2,size = (256,256)): 
    # 将图像resize后,分离为三个通道,再计算每个通道的相似值 
    image1 = cv2.resize(image1,size) 
    image2 = cv2.resize(image2,size) 
    sub_image1 = cv2.split(image1) 
    sub_image2 = cv2.split(image2) 
    sub_data = 0
    for im1,im2 in zip(sub_image1,sub_image2): 
        sub_data += calculate(im1,im2) 
    sub_data = sub_data/3
    return sub_data 
  
# 平均哈希算法计算 
def classify_aHash(image1,image2): 
    image1 = cv2.resize(image1,(8,8)) 
    image2 = cv2.resize(image2,(8,8)) 
    gray1 = cv2.cvtColor(image1,cv2.COLOR_BGR2GRAY) 
    gray2 = cv2.cvtColor(image2,cv2.COLOR_BGR2GRAY) 
    hash1 = getHash(gray1) 
    hash2 = getHash(gray2) 
    return Hamming_distance(hash1,hash2) 
  
def classify_pHash(image1,image2): 
    image1 = cv2.resize(image1,(32,32)) 
    image2 = cv2.resize(image2,(32,32)) 
    gray1 = cv2.cvtColor(image1,cv2.COLOR_BGR2GRAY) 
    gray2 = cv2.cvtColor(image2,cv2.COLOR_BGR2GRAY) 
    # 将灰度图转为浮点型,再进行dct变换 
    dct1 = cv2.dct(np.float32(gray1)) 
    dct2 = cv2.dct(np.float32(gray2)) 
    # 取左上角的8*8,这些代表图片的最低频率 
    # 这个操作等价于c++中利用opencv实现的掩码操作 
    # 在python中进行掩码操作,可以直接这样取出图像矩阵的某一部分 
    dct1_roi = dct1[0:8,0:8] 
    dct2_roi = dct2[0:8,0:8] 
    hash1 = getHash(dct1_roi) 
    hash2 = getHash(dct2_roi) 
    return Hamming_distance(hash1,hash2) 
  
# 输入灰度图,返回hash 
def getHash(image): 
    avreage = np.mean(image) 
    hash = [] 
    for i in range(image.shape[0]): 
        for j in range(image.shape[1]): 
            if image[i,j] > avreage: 
                hash.append(1) 
            else: 
                hash.append(0) 
    return hash
  
  
# 计算汉明距离 
def Hamming_distance(hash1,hash2): 
    num = 0
    for index in range(len(hash1)): 
        if hash1[index] != hash2[index]: 
            num += 1
    return num 
  
  
if __name__ == '__main__': 
    img1 = cv2.imread('1.jpg') 
    #cv2.imshow('img1',img1) 
    img2 = cv2.imread('1.png') 
    #cv2.imshow('img2',img2) 
    degree = classify_gray_hist(img1,img2) 
    #degree = classify_hist_with_split(img1,img2) 
    #degree = classify_aHash(img1,img2) 
    #degree = classify_pHash(img1,img2) 
    print( degree) 
    #cv2.waitKey(0)

测试一个jpg和转成png的结果比较,相似度为93.6%

参考:http://www.jb51.net/article/83315.htm?t=1479218868974

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程圈子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值