1. 程式人生 > >【小聰明】圖片消失在另一張圖片裏

【小聰明】圖片消失在另一張圖片裏

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")

【小聰明】圖片消失在另一張圖片裏