Python3 圖像識別(二)


Infi-chu:

http://www.cnblogs.com/Infi-chu/

以圖搜圖的使用已經非常廣泛了,我現在來介紹一下簡單的以圖搜圖的相關算法及其實踐。

一、感知hash算法

感知哈希算法:
感知哈希算法(Perceptual hash algorithm)是哈希算法的一類,主要用來做相似圖片的搜索工作。
圖片所包含的特征被用來生成一組指紋(不過它不是唯一的), 而這些指紋是可以進行比較的。
步驟:
1.把圖片轉化為字符串,這個字符串就是圖片的hash值,又稱指紋。
2.求兩個字符串之間的相似度(漢明距離),字符串越相似,即圖片越相似。

 二、漢明距離

漢明距離:
漢明距離是兩個字符串對應位置的不同字符的個數。換句話說,它就是將一個字符串變換成另外一個字符串所需要替換的字符個數。
例如:
1011101 與 1001001 之間的漢明距離是 2。
2143896 與 2233796 之間的漢明距離是 3。
“toned” 與 “roses” 之間的漢明距離是 3。

三、均值hash

下面的例子是使用了像素平均值,又叫均值哈希。
優點:均值哈希較為簡單。
缺點:對圖像灰度的平均值特別敏感,也不具備旋轉不變性。
import cv2
def p_hash(path):
    # Step1. 把圖像縮小為8 * 8,並轉化為灰度圖
    src = cv2.imread(path, 0)
    src = cv2.resize(src, (8, 8), cv2.INTER_LINEAR)
    # Step2. 計算64個像素的灰度均值
    avg = sum([sum(src[i]) for i in range(8)]) / 64
    #  Step3. 與平均值比較,生成01字符串
    string = ''
    for i in range(8):
        string += ''.join(map(lambda i: '0' if i < avg else '1', src[i]))
    # Step4. 計算hash值
    result = ''
    for i in range(0, 64, 4):
        result += ''.join('%x' % int(string[i: i + 4], 2))
        return result

def hamming(str1, str2):
    if len(str1) != len(str2):
        return
    count = 0
    for i in range(0, len(str1)):
        if str1[i] != str2[i]:
            count += 1
    return count

# 讀取四張圖片,進行測試
h1 = p_hash('1.jpg')
h2 = p_hash('2.jpg')
h3 = p_hash('3.jpg')
h4 = p_hash('4.jpg')

# 四張圖片的相互對比
print('1&2 --> ',hamming(h1,h2))
print('1&3 --> ',hamming(h1,h3))
print('1&4 --> ',hamming(h1,h4))
print('2&3 --> ',hamming(h2,h3))
print('2&4 --> ',hamming(h2,h4))
print('3&4 --> ',hamming(h3,h4))

結果:

1&2 -->  1
1&3 -->  0
1&4 -->  1
2&3 -->  1
2&4 -->  1
3&4 -->  1

四、余弦感知哈希

為了提升更好的識別效果,可以使用余弦感知哈希算法。
優點:能夠處理旋轉圖形。
缺點:只能夠識別變形程度在25%以內的圖片。

步驟:
1.縮小尺寸:將圖像縮小到32*32,並轉為灰度圖。
2.計算DCT:對圖像進行二維離散余弦變換。
3.縮小DCT:只保留矩陣左上角8*8區域,對這個區域求哈希均值,並生成01字符串。
4.計算hash值。
5.求漢明距離
import numpy as np
import cv2

def p_hash(path):
    # Step1. 把圖像縮小為32 * 32,並轉化為灰度圖
    src = cv2.imread(path, 0)
    src = cv2.resize(src, (32, 32), cv2.INTER_LINEAR)

    # Step2. 對圖像進行余弦變換
    h, w = src.shape[:2]
    arr = np.zeros((h, w), np.float32)
    arr[:h, :w] = src
    src = cv2.dct(cv2.dct(arr))  # 離散余弦變換
    src.resize(8, 8)

    # Step3. 計算64個像素的灰度均值
    avg = sum([sum(src[i]) for i in range(8)]) / 64

    # Step4. 與平均值比較,生成01字符串
    string = ''
    for i in range(8):
        string += ''.join(map(lambda i: '0' if i < avg else '1', src[i]))

    # Step5. 計算hash值
    result = ''
    for i in range(0, 64, 4):
        result += ''.join('%x' % int(string[i: i + 4], 2))
    return result


def hamming(str1, str2):
    if len(str1) != len(str2):
        return
    count = 0
    for i in range(0, len(str1)):
        if str1[i] != str2[i]:
            count += 1
    return count

# 讀取四張圖片,進行測試
h1 = p_hash('1.jpg')
h2 = p_hash('2.jpg')
h3 = p_hash('3.jpg')
h4 = p_hash('4.jpg')

# 四張圖片的相互對比
print('1&2 --> ',hamming(h1,h2))
print('1&3 --> ',hamming(h1,h3))
print('1&4 --> ',hamming(h1,h4))
print('2&3 --> ',hamming(h2,h3))
print('2&4 --> ',hamming(h2,h4))
print('3&4 --> ',hamming(h3,h4))
print('1&1 --> ',hamming(h1,h1))

結果:

1&2 -->  3
1&3 -->  1
1&4 -->  6
2&3 -->  3
2&4 -->  6
3&4 -->  5
1&1 --> 0

圖例:

‘1.jpg’

‘2.jpg’

 

‘3.jpg’

 

‘4.jpg’

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM