【每週一坑】圖像的指紋:數字水印 + 【解答】雞兔同籠

曾經有過這樣的新聞:某公司的員工將內網論壇上的言論截屏發佈到互聯網上,引發了熱議。於是公司通過截圖定位到了員工的身份,將其開除。

有人可能好奇,僅憑截圖就能知道是誰幹的嗎?這裏就是用到了“數字水印”技術。

數字水印(Digital Watermarking)技術是將一些標識信息(即數字水印)直接嵌入數字載體當中(包括多媒體、文檔、軟件等)或是間接表示(修改特定區域的結構),且不影響原載體的使用價值,也不容易被探知和再次修改。但可以被生產方識別和辨認。 — 百度百科

只要在你看的頁面上嵌入了肉眼不可見的信息,記錄你的身份,之後再通過相應的解碼軟件從流出的截屏上提取出這些信息,就能知道你是誰了。

數字水印的應用還包括防僞防篡改保護版權等場景。

數字水印是個很大的範疇,有很多實現方式,具有不同的實現難度、信息容量、抗攻擊性、對原圖的干擾等。

這裏我們介紹一種很簡單的實現方式:

  1. 圖像中的每個像素通常可以用 RGB(紅綠藍)三個 0~255 的值來表示。如果把這個值轉成二進制來表示,就是 00000000~11111111
  2. 把每個值的最後1位全部設成0,對圖像的影響非常細微,人眼無法察覺。
  3. 這樣,空出來的最後1位就可以拿來存儲信息。把水印字符轉成二進制,依次填入這些位置上,就完成了信息的嵌入。
  4. 提取信息就是上述的逆過程:把圖像的像素信息取出來,提取最後1位,拼出信息。

今天我們的題目就是:請將一段文字嵌入到一張圖片中,然後再成功地復原出來。

示例原圖:

嵌入信息後:

提取信息:

相比較之前的題目,這期的問題難道稍高,因此再給一些提示:

  1. 之前幾次圖像處理用到的 PIL 庫,可以方便得到圖像的像素值,以及保存新圖像。
  2. 將一個字符 c 轉成二進制表示:bin(ord(c))[2:],反之:chr(int(s, 2))
  3. 將一個整數 x 的二進制末位設爲 0x // 2 * 2
  4. 處理後的圖像需要保存成 pngbmp,因爲 jpg 是有損壓縮,無法保證像素值不變。
  5. 仍然沒有頭緒的話,可以網上搜索“python 數字水印”尋找參考

詳細解答和參考代碼將在下次欄目中給出,也可以其他同學在留言中的代碼

期待各位同學提交解答。

提交代碼可以使用 paste.ubuntu.com

codeshare.io 等代碼分享網站,只需將代碼複製上去保存,即可獲得一個分享地址,非常方便。

往期問題可通過公衆號菜單欄“課外輔導”欄目中進入查看。


【解答】雞兔同籠

上一次的題目 【每週一坑】雞兔同籠 +【解答】房貸計算器 看來是比較簡單,因爲是本欄目到目前爲止提交答案最多的一次。

大家的解法主要有三種:

1. 枚舉法

即循環假設雞數或兔數,驗證是否滿足頭數和腳數的條件。

參考解答:

def calc_count(m, n):
    for c in range(m+1):
        r = m - c
        if c * 2 + r * 4 == n:
            return c, r
    return 0, 0

m = int(input('heads(m):'))
n = int(input('feet(n):'))
c, r = calc_count(m, n)
if c == r == 0:
    print('invalid input')
else:
    print('cocks', c, 'rabbits', r)

TY、penger、GS、?ེི、Famisi、Bun、張釩、神無月、扶南、喵喵 等同學用了此方法。

2. 計算法

此方法即直接使用推導出的數學算式,計算出結果。

知寒 、Fiat Lux、臧貴城、胖胖萌、閻雷、Butter.Fly.、王文亞、Mayo、燦夜、徐大龍、一休叔叔、會飛的貓、laughing…、╮(╯▽╰)╭、鑫HEAD、A暴躁的眼鏡吳 等同學用了此方法。

王目田|xa 同學的代碼實現了以上兩種方式。

3. 解方程法

利用 sympynumpy 模塊裏的解方程工具,通過二元方程求解。

曹東、小魚乾拿來啦、花兒笑了、shadowsong 用了這種方式。

雖然從這個問題來看,枚舉法有點多餘,直接計算很方便。但我想說的是,枚舉法更具有“編程的思維”。編程新手可以體會下二者的區別。

感謝各位同學的參與。

期待在下一期中看到你的代碼!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章