【小聰明】圖片消失在另一張圖片裏
阿新 • • 發佈:2018-04-01
http markdown hide align blog ide reat 就是 ref
。
概要
?
偶然看到一篇文章偽·黑科技】基於像素微調實現的文字隱寫術,受此啟發,能把文字轉成二進制,那麽圖片像素轉成二進制豈不更容易,於是我就寫了一個隱藏圖片的代碼,也就有了這篇隨筆。
但是剛寫出來不完美,有幾點需要改進的地方,現在還沒有想通,做此記錄,以後有機會再慢慢改進:
- python 包 matplotlib 保存數組構成的圖片時,會自動加個透明層,即不是我想要的 RGB 格式,而是 RGBA 格式。why,why,不得不轉向其它包
- 包存圖片格式時,一般的數組有可能格式不對,如果遇到錯誤,就保存為 unit8 格式
?
效果圖
?
提示:這是我截的圖,不是原圖,像素可能不滿足要求,做實驗可用自己的圖片
圖 1:要被隱藏的圖片
圖 2:隱藏之後的圖片效果圖
代碼
?
基本的原理就是利用二進制微調宿主像素。代碼中的解釋已經很清楚了,在此不再多述。
# -*- coding: utf-8 -*-
"""
Created on Thu Mar 29 11:47:43 2018
@author: zhoukui
"""
import numpy as np
from PIL import Image
import matplotlib.image as mpimg
import sys
def image2Bin(imageFile):
image = mpimg.imread(imageFile)
imageArr = image.ravel()
binList = list((map(bin,imageArr)))
for i, item in enumerate(binList): # 把數字全部轉換為 8 位的 0 1 數據
binList[i] = item[2:] # 把二進制標誌 '0b' 去掉
binList[i] = '0'*(8 - len(binList[i])) + binList[i]
pixes_x, pixes_y, _ = image.shape # 把原始圖片像素保存一下
binX = bin(pixes_x)[2:]
binY = bin(pixes_y)[2:]
binList.insert(0,'0'*(16-len(binX)) + binX)
binList.insert(1,'0'*(16-len(binY)) + binY)
# 前兩個 16 位表示的是像素長寬,像素長寬相乘再乘以 3 得到後面 8 位的數目
return binList
def showImage(imageArr, imageTitle):
im = Image.fromarray(imageArr)
im.save(imageTitle)
im.show()
def oneHide(pix, pixValue):
if pix == '0': # 使圖片像素變為偶數
if pixValue == 255:
pixValue = 244
elif pixValue % 2 == 1:
pixValue += 1
elif pixValue % 2 == 0:
pixValue += 1
return pixValue # 返回去改變這像素值
def hiding(binList, hidingImageFile):
image = mpimg.imread(hidingImageFile)
#print(image.shape)
imageArr = image.ravel()
# 每一個像素隱藏一個 0 或者 1
# 判斷是否藏得下
if (len(binList)*8+16 > len(imageArr)):
print("藏不下,換一張宿主更大的圖片或把要藏的圖片調小")
else:
flag = 0 # 標記藏到哪了
# 先藏前兩個 16 位的
for i in range(2):
for j in range(16):
imageArr[flag] = oneHide(binList[i][j], imageArr[flag])
flag += 1
# 然後藏剩下的
for _, item in enumerate(binList[2:]):
if flag % 8640 == 0:
sys.stdout.write('\r complete percent ----->:%.0f%%' % (flag/82976.))
for j in range(8):
imageArr[flag] = oneHide(item[j], imageArr[flag])
flag += 1
sys.stdout.flush()
#print(imageArr[:8])
imageArr = imageArr.reshape(image.shape) #.astype(np.uint8)
return imageArr
def imerging(imageFile):
image = mpimg.imread(imageFile) # 這種讀取圖片直接是 Ndarray
imageArr = image.ravel()
# 先把隱藏圖片的大小解析出來
tempList = [str(i % 2) for i in imageArr[:32]]
pixesX = int(''.join(tempList[:16]), 2)
pixesY = int(''.join(tempList[16:]), 2)
#print(pixesX, pixesY)
# 把隱藏圖片的像素解析出來
temp2List = [str(i % 2) for i in imageArr[32 : 32 + pixesX*pixesY*3*8]]
tempArr = np.zeros(pixesX*pixesY*3,)
for i in range(pixesX*pixesY*3):
tempArr[i] = int(''.join(temp2List[8*i:8*(i+1)]), 2)
#sys.stdout.flush()
tempArr = tempArr.reshape(pixesX, pixesY, 3).astype(np.uint8) # 不加會模糊
showImage(tempArr, "image_after_decreption.bmp")
def imageEncre(hidedImageFile, hidingImageFile):
# 可視化隱藏前圖片
#imageArrBefore = mpimg.imread(hidingImageFile)
#showImage(imageArrBefore, "image before hiding")
# 把要加密的圖片轉換成 0 1 數字
print("加密前準備工作...")
binList = image2Bin(hidedImageFile)
# 接下來把 0 與 1 藏進另一張圖片
print("開始加密...")
imageArrAfter = hiding(binList, hidingImageFile)
#print(imageArrAfter[:8,:,:])
showImage(imageArrAfter, "image_after_encreption.bmp")
def imageDecre(imageFile):
print("解碼中...")
imerging(imageFile)
if __name__ == "__main__":
#imageEncre("hided.jpg", "hiding.jpg")
imageDecre("image_after_encreption.bmp")
【小聰明】圖片消失在另一張圖片裏