# 图像哈希二进制字符串相互转换以及flatten()的用法

def _binary_array_to_hex(arr):
"""
internal function to make a hex string out of a binary array.

binary array might be created from comparison - for example, in
average hash, each pixel in the image is compared with the average pixel value.
If the pixel's value is less than the average it gets a 0 and if it's more it gets a 1.
Then we treat this like a string of bits and convert it to hexadecimal.
"""
h = 0
s = []
for i, v in enumerate(arr.flatten()):
if v:
h += 2**(i % 8)
if (i % 8) == 7:
s.append(hex(h)[2:].rjust(2, '0'))
h = 0
return "".join(s)

#-*- coding:utf-8 -*-
from PIL import Image
import imagehash
from numpy import *

def hashToStr(hh):
s = []
for i in range(8):
for j in range(8):
y = int(hh[i][j])
s.append(str(y))

return "".join(s)

def strToHash(strh):
l = []
if len(strh) != 64:
emsg = 'Expected str string size of {}'
raise ValueError(emsg.format(64))
ll = []
for i in range(len(strh)):
if len(ll) == 8:
l.append(ll)
ll = []
ll.append(int(strh[i]) > 0)
else:
ll.append(int(strh[i]) > 0)
l.append(ll)
return imagehash.ImageHash(array(l))

if __name__ == '__main__':
img = Image.open('C:/Users/wanglx1/workspace/imagehash/similarity/3.jpg')
h = imagehash.phash(img)
print('h :',h)   #得到的hash是一个8*8的数组，不过此时的h是一个imagehash的对象
# ('h :', array([[ True, False, False,  True, False, False,  True, False],
#       [ True,  True, False, False,  True,  True,  True, False],
#       [ True, False,  True,  True, False, False,  True,  True],
#       [False, False,  True,  True, False, False,  True,  True],
#       [ True,  True, False, False,  True, False,  True, False],
#       [ True,  True, False,  True, False, False,  True,  True],
#       [ True, False, False,  True,  True, False, False,  True],
#       [False, False, False,  True, False,  True, False, False]], dtype=bool))
print('h.hash :',h.hash)
# ('h.hash :', array([[ True, False, False,  True, False, False,  True, False],
#      [ True,  True, False, False,  True,  True,  True, False],
#      [ True, False,  True,  True, False, False,  True,  True],
#      [False, False,  True,  True, False, False,  True,  True],
#      [ True,  True, False, False,  True, False,  True, False],
#      [ True,  True, False,  True, False, False,  True,  True],
#      [ True, False, False,  True,  True, False, False,  True],
#      [False, False, False,  True, False,  True, False, False]], dtype=bool))
#对外操作，要用h.hash才可以。
#想知道为什么看源码就明白了。
hh = h.hash
strh = hashToStr(hh)
print('strh :',strh) #输出二进制字符串
#('strh :', '1001001011001110101100110011001111001010110100111001100100010100')

hashh = strToHash(strh)  #此时得到的是ImageHash的对象，可以使用ImageHash类定义的函数进行运算
print('hashh :',hashh.hash)
# ('hashh :', array([[ True, False, False,  True, False, False,  True, False],
#       [ True,  True, False, False,  True,  True,  True, False],
#       [ True, False,  True,  True, False, False,  True,  True],
#       [False, False,  True,  True, False, False,  True,  True],
#       [ True,  True, False, False,  True, False,  True, False],
#       [ True,  True, False,  True, False, False,  True,  True],
#       [ True, False, False,  True,  True, False, False,  True],
#       [False, False, False,  True, False,  True, False, False]], dtype=bool))
print(shape(hashh.hash))
#(8L, 8L)

• arr是一个数组，flatten（）是将数组转化成一个向量
• 关于flatten在数组矩阵列表中的用法如下：

b = [[1,2,3],[4,5,6]]
b = mat(b)
print (b)

#[[1 2 3]
# [4 5 6]]

print('b',b.flatten())  #对矩阵

#('b', matrix([[1, 2, 3, 4, 5, 6]]))

print (shape(b.flatten()))
#(1L, 6L)

a = array([[1,2],[3,4]]) #数组

print ('sdfs',a.flatten())
#('sdfs', array([1, 2, 3, 4]))
print (shape(a.flatten()))
#(4L,)

c = [[1,2,4],[5,6,7]] #列表 有错误

print c
# print c.flatten()
#AttributeError: 'list' object has no attribute 'flatten'