1. 程式人生 > >簡單的程式猿表白 圖片隱寫 --顏色通道的微改

簡單的程式猿表白 圖片隱寫 --顏色通道的微改

參考部落格:https://www.cnblogs.com/taceywong/p/4858933.html

今天這裡小編介紹一種簡單的屬於我們程式猿的表白方式 --圖片隱寫。

圖片的隱寫術有很多種,像檔案尾新增檔案,LSB隱寫演算法……這些都是比較常見的方法,

圖片隱寫有什麼用呢?圖片本身的作用是通過影象傳遞資訊,但是圖片本身是一種檔案,在這個特定的檔案中我們可以在其中隱藏資訊,也可以將其作為簽名,畢竟現實中照片我們可以背面簽名,而計算機中圖片可有著無數種“背面”,給了我們簽名留下了很大的空間

這裡小編介紹一種簡單的圖片隱寫方法,這種隱寫方法用到的主要原理也是和我們視覺有關的。


那麼這裡小編給出一個矩形,如果這裡小編問大家這個矩形是什麼顏色的,那麼大家的說法肯定會非常一致,“黑色”。

其實不然……

這裡的這個矩形其實是由無數種顏色組合在了一起,但是由於這些畫素點上的顏色差異很低,所以其實在大家眼裡這就是一種顏色“黑色”。

在計算機中,顏色可以用三原色調出來,也就是我們熟知的RGB(紅色,綠色,藍色),我們可以用著三原色的值來表示所有的顏色RGB值的範圍都是0~255(R:0 G:0 B:0為黑色,R:255 G:255 B:255為白色)。

當我們將這種表示方式的其中一個值改動1的話,其實我們眼睛是分不出來的。

那麼到這裡跟我們這種隱寫方法有沒有什麼關係呢?

有的,其實原理的重點就是微小改動值我們眼睛不會發現什麼異常。

好,介紹完原理,我們開始實際操作。

第一步,搞到一張BMP格式的圖片:

為什麼是BMP格式的呢?為什麼不用我們常見的JPG和PNG格式的呢?

這裡還是要介紹一下BMP格式,BMP的全稱是BitMap,這種格式的圖片是Windows作業系統下的標準影象檔案格式,它採用位對映儲存格式,除了影象深度可選以外,不採用其他任何壓縮,因此這種格式的圖片可能會比較大,但是不壓縮這個特性對我們來說很關鍵。這樣我們就可以精確的控制畫素值,但是其他格式的圖片,如JPG、PNG,都會進行壓縮,使得畫素值會有比較小的波動,有波動我們就不方便去操作了,所以這裡最好還是用BMP格式的。

這裡小編際操作了一下,找自己喜歡了很久的一個女生要了一張照片,哎,吐槽一句,本來我還想的是要一張原圖,然後靠著自己精湛的技術P好看一點,然後再用隱寫方法誇她兩句,然而這個女生蠢的一逼,居然不知道怎麼發文件(/= _ =)/~┴┴,沒辦法,只好在她qq空間裡面拉了一張被壓縮過的噪點滿滿的照片,開啟一看,這麼糊怎麼P,哎,繞過第一步,直接隱寫吧(表白吧)……


我們先將這個圖片的資料矩陣讀出來。這裡提出一種很好的區分方法,我們將所有的畫素點的R值(這裡用G值和B值都是一樣的,沒有區別)都改為偶數,如果一個畫素點的R值本身是偶數的話,那麼不需要改動,如果是奇數的話,那麼+1/-1就能完成操作,而剛剛的原理解釋中我們提到微小改動值我們眼睛不會發現什麼異常。所以這裡的改動我們在圖片上實際看不出什麼區別。

第二步,搞到一張大小一樣的空的BMP格式的圖片:

整個步驟我們都能用PS搞定。在這張空的圖片上我們用顏色為真正的黑色(R:0 G:0 B:0)寫下我們要隱寫的內容,注意,這一步我們要用的是準確的RGB值,而不是隨手在畫板工具上隨手選一個顏色,因為我們後面是需要精確的對RGB值進行處理的。搞好之後也是要儲存為BMP格式哦


接下來我們也同樣去讀這張圖片的資料矩陣,這張圖上之後兩種顏色,黑色(R:0 G:0 B:0)和白色(R:255 G:255 B:255),所以很好區分,那麼這裡我們將這個圖片中黑色也就是我們文字顏色的畫素點對應到在之前的照片的畫素點,然後再將這些圖片的R通道值改為奇數,這一操作同樣是+1/-1就能完成的,所以一樣改動不會造成視覺上的差異。

這樣我們的隱寫過程就結束了。

可能到這裡很多同學還不明白,這怎麼就結束了?為了讓大家更好的去理解這個過程,我們再來對這張圖片進行隱寫的解密吧。

回憶一下現在這張圖的情況,整張圖片的所有畫素點的R值幾乎都為偶數,只有我們第二張圖中出現文字的地方的畫素點的R值為奇數,那麼這裡解密的處理操作就是將所有R值為奇數的點的顏色調成一樣(黑色),講所有R值為偶數的點顏色調成一樣(白色),那麼處理過後我們就能看到這句專屬的簽名(表白)啦!

祝所有引用次表白方式的程式猿們表白成功!!!

原始碼:

hide.py:

import cv2
import numpy
img = cv2.imread("1.bmp")
code = cv2.imread("2.bmp")
w,h = img.shape[:2]
for i in range(w):
    for j in range(h):
        if img[i,j,2] %2 != 0:
            img[i,j,2] = img[i,j,2]+1 if img[i,j,2] <2 else img[i,j,2]-1
for i in range(w):
    for j in range(h):
        if code[i,j,0] == 0 and code[i,j,1] == 0 and code[i,j,2] == 0:
            img[i,j,2] += 1
cv2.imwrite("3.bmp",img)
get.py:
import cv2
import numpy
img = cv2.imread("3.bmp")
out = numpy.zeros(img.shape,np.uint8)
w,h = img.shape[:2]
for i in range(w):
    for j in range(h):
        if img[i,j,2] %2 != 0:
            out[i,j,0]=255
            out[i,j,1]=255
            out[i,j,2]=255
cv2.imwrite("4.bmp",out)