Python實(shí)現(xiàn)在圖像中隱藏二維碼的方法詳解
一、前言
在某個App中有一個加密水印的功能,當(dāng)帖子的主人開啟了之后。如果有人截圖,那么這張截圖中就是添加截圖用戶、帖子ID、截圖時間等信息,而且我們無法用肉眼看出這些水印。
這可以通過今天要介紹的隱寫技術(shù)來實(shí)現(xiàn),我們會通過這種技術(shù),借助Python語言和OpenCV模塊來實(shí)現(xiàn)在圖像中隱藏二維碼的操作。而且這個二維碼無法通過肉眼看出。
二、隱寫
隱寫是一種類似于加密卻又不同于加密的技術(shù)。通常情況下,加密是對數(shù)據(jù)本身進(jìn)行一個轉(zhuǎn)換,得到的結(jié)果是一堆人無法解讀的數(shù)據(jù),比如“你好”進(jìn)行md5加密后的結(jié)果是“7eca689f0d3389d9dea66ae112e5cfd7”,如果光看“7eca689f0d3389d9dea66ae112e5cfd7”我們不知道內(nèi)容,但是我們知道這應(yīng)該是加密后的數(shù)據(jù)。隱寫的目的同樣是讓只有接收方才能獲取數(shù)據(jù),但是隱寫通常更加隱蔽,隱寫更注重于不讓第三方知道我發(fā)送的數(shù)據(jù)中有額外信息。
就像我們在電影中經(jīng)常看到的一些劇情,一場看似普通的對話卻隱含了許多外人不知道的信息,這實(shí)際上就是一種隱寫。再比如“This is a pig”,看上去像一個普通的句子,如果通信雙方規(guī)定“T、i、s”這些占三線格上兩個的字母表示0,而“p、g”這種占三線格下兩格的字母表示1,那么這句話就可以翻譯成“0000000101”。而今天我們要介紹的是“最低有效位”隱寫。
三、位平面分解
在介紹“最低有效位”隱寫之前,需要了解一些圖像相關(guān)的知識。這里包括數(shù)字圖像、位平面、位平面分解。
3.1 圖像
在計(jì)算機(jī)中,圖像被表示為一個數(shù)字矩陣,每個數(shù)字被稱為一個像素,它們的取值在[0, 255]區(qū)間,可以用8個二進(jìn)制來表示。
這個矩陣大小由圖像分辨率決定,如果是480×480分辨率的圖像,那么這個矩陣大小就是480×480。如果是彩色圖像,會用三個大小相同的矩陣合起來表示,它們分別表示圖像R(紅色)、G(綠色)、B(藍(lán)色)的程度,也就是俗稱的RGB圖像。
我們可以用OpenCV來讀取圖像,OpenCV的安裝如下:
pip install opencv-python
安裝完成后就可以讀取圖像:
# 導(dǎo)入模塊 import cv2 # 讀取圖像 img = cv2.imread('test.jpg') # 輸出圖像 print(img)
其中test.jpg就是我們的圖像名稱或者圖像路徑。上面代碼輸出結(jié)果如下:
[[[ 72 220 234]
[ 72 220 234]
[ 73 221 235]
...
[ 87 147 176]
[ 87 147 176]
[ 87 147 176]]]
因?yàn)檩敵鲞^長,這里省略了一部分內(nèi)容。
3.2 位平面
在前面我們說了一個圖像是一個數(shù)字矩陣,比如:
[[2, 2]
[3, 4]]
我們可以理解為一張簡單的圖像,現(xiàn)在我們把圖像的像素值寫成二進(jìn)制形式:
[[0000 0010, 0000 0010],
[0000 0011, 0000 0100]]
我們把四個像素的最高位取出,得到新的圖像:
[[0, 0]
[0, 0]]
這個過程的圖示如下:
這里取出來的圖像就叫位平面,因?yàn)槭侨〕龅?位(從左到右依次是7-0)組成的圖像,所以叫第7位平面,也叫最高位平面。而第0位平面也叫“最低有效位”位平面。
如果取出第1位,得到的圖像為:
[[1, 1],
[1, 0]]
這個圖像叫第1位平面。這里需要注意一點(diǎn),就是每個位平面的實(shí)際值應(yīng)該乘一個權(quán)重,這個權(quán)重位i2,即第7位平面的權(quán)重位72。
3.3 位平面分解
下面我們看看如何分解位平面,分解位平面可以用cv2.bitwise_and函數(shù)來實(shí)現(xiàn)。我們需要傳入一個圖像以及一個分解因子,各個位平面的分解因子如下:
分解因子 | 作用 |
---|---|
0x80 | 分解第7位平面 |
0x40 | 分解第6位平面 |
0x20 | 分解第5位平面 |
0x10 | 分解第4位平面 |
0x08 | 分解第3位平面 |
0x04 | 分解第2位平面 |
0x02 | 分解第1位平面 |
0x11 | 分解第0位平面 |
比如分解第7位平面的操作為:
import cv2 # 讀取圖像 img = cv2.imread('test.jpg', 0) # 分解第7位平面 layer = cv2.bitwise_and(img, 0x80)
其它位平面的分解只需要對照表進(jìn)行修改即可。
3.4 位平面合成
假如我們以及分解出來8個位平面,分別是M0、M1、…、M7。我們只需要將各個位平面乘上對應(yīng)的權(quán)重,然后相加就能恢復(fù)原圖,即:
如果我們只對M1-M7進(jìn)行合成,得到的A`與A的差距最多為1,因此我們可以讓A`≈A。此時圖像A`的第0個位平面可以用于隱藏?cái)?shù)據(jù)。
四、圖像隱寫
這里我們使用一種叫“最低有效位”位平面隱寫的技術(shù)來實(shí)現(xiàn)二維碼的隱藏。其原理就是把圖像“最低有效位”位平面設(shè)置為0,此時圖像與原圖像像素相差最大為0,人肉眼無法看出區(qū)別。然后我們可以在圖像的最低有效位任意設(shè)置值,此時圖像與原圖像素相差最大仍是1。這樣我們就可以用“最低有效位”位平面來隱寫數(shù)據(jù)。
在前面我們合成原圖時用M1-M7,而M0位平面則全為0,這時我們可以用最低有效位存儲數(shù)據(jù)。假如我們的數(shù)據(jù)矩陣為M,該矩陣為一個0-1矩陣。而二維碼就是一個黑白矩陣,我們可以把黑當(dāng)作0,白當(dāng)作1,這樣我們讓M為一個二維碼的矩陣?,F(xiàn)在我們通過下面的公式來合成:
這個A就是帶有隱寫信息的圖像。代碼實(shí)現(xiàn)如下:
import cv2 # ①讀取圖像 img = cv2.imread('test.jpg', 0) # ②把最低有效位清空 img -= cv2.bitwise_and(img, 0x01) # ③準(zhǔn)備需要隱寫的信息M M = cv2.imread('qrcode.jpg', 0) M = cv2.resize(M, img.shape) # 把二維碼轉(zhuǎn)換成0-1矩陣 _, M = cv2.threshold(M, 30, 1, cv2.THRESH_BINARY) # ④將要隱寫的數(shù)據(jù)設(shè)置到圖像最低有效位 img += M # ⑥以無損的方式保存隱寫后的 cv2.imwrite('dst.png', img, [int(cv2.IMWRITE_JPEG_QUALITY), 100])
最后保存的dst.png就是我們隱寫后的圖像。
二維碼的生成可以參考詳解Python如何生成優(yōu)雅的二維碼
到此這篇關(guān)于Python實(shí)現(xiàn)在圖像中隱藏二維碼的方法詳解的文章就介紹到這了,更多相關(guān)Python圖像隱藏二維碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Django 實(shí)現(xiàn)Admin自動填充當(dāng)前用戶的示例代碼
今天小編就為大家分享一篇Django 實(shí)現(xiàn)Admin自動填充當(dāng)前用戶的示例代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11python通過函數(shù)名調(diào)用函數(shù)的幾種場景
這篇文章主要介紹了python通過函數(shù)名調(diào)用函數(shù)的幾種場景,幫助大家更好的理解和使用python,感興趣的朋友可以了解下2020-09-09神經(jīng)網(wǎng)絡(luò)python源碼分享
這篇文章主要介紹了神經(jīng)網(wǎng)絡(luò)python源碼分享,具有一定借鑒價值,需要的朋友可以參考下。2017-12-12Python3.9 beta2版本發(fā)布了,看看這7個新的PEP都是什么
這篇文章主要介紹了Python3.9 beta2版本發(fā)布了,看看這7個新的PEP都是什么,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2020-06-06python全棧要學(xué)什么 python全棧學(xué)習(xí)路線
在本文中小編給大家整理了關(guān)于python全棧要學(xué)什么以及python全棧學(xué)習(xí)路線的知識點(diǎn)內(nèi)容,需要的朋友們參考下。2019-06-06python3 使用traceback定位異常實(shí)例
這篇文章主要介紹了python3 使用traceback定位異常實(shí)例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03Python實(shí)現(xiàn)一個簡單的驗(yàn)證碼程序
這篇文章主要介紹了Python實(shí)現(xiàn)一個簡單的驗(yàn)證碼程序,具有一定參考價值,需要的朋友可以了解下。2017-11-11