Arnold變換詳解

1. 概述

利用Arnold變換(又稱(chēng)貓臉變換)可以對(duì)圖像進(jìn)行置亂,使得原本有意義的圖像變成一張無(wú)意義的圖像。該變換可以在其它圖像處理前對(duì)圖像做預(yù)處理,例如在數(shù)字盲水印嵌入前對(duì)水印進(jìn)行置亂。也可以用于普通的圖像加密。
通常一次Arnold變換達(dá)不到理想效果,需要對(duì)圖像進(jìn)行連續(xù)多次的變換。Arnold變換具有周期性,即對(duì)圖像連續(xù)進(jìn)行Arnold變換,最終又能得到原圖像。變換的周期和圖像的尺寸有關(guān)。
當(dāng)圖像是一張方形的圖像時(shí),Arnold變換存在逆變換。經(jīng)過(guò)N次Arnold變換后的數(shù)據(jù)可以通過(guò)N次逆變換恢復(fù)數(shù)據(jù)。
Arnold變換不僅可以用于圖像置亂,也可以用于其它數(shù)據(jù)的置亂和加密。

2. 狹義的貓臉變換

2.1 公式

狹義的貓臉變換即最簡(jiǎn)單的一種變換。網(wǎng)絡(luò)上絕大部分關(guān)于Arnold變換的博客都是狹義Arnold變換。
其矩陣運(yùn)算公式為:

狹義貓臉變換矩陣公式

轉(zhuǎn)化為多項(xiàng)式為:
狹義貓臉變換多項(xiàng)式公式

其中mod()是取模運(yùn)算,N是正方形圖像的邊長(zhǎng),(x', y')是像素點(diǎn)(x, y)變換后的坐標(biāo)。
注意求模運(yùn)算(mod) ≠ 求余運(yùn)算(%) 。在被除數(shù)是負(fù)數(shù)時(shí)兩者存在差別,例如: -5 mod(6) = 1, 但 -5 % 6 = -5。

/**
 * 求模運(yùn)算
 */
private int mod(int number, int mod) {
    return (number % mod + mod) % mod;
}

2.2 物理意義和示意圖

置亂的實(shí)質(zhì)是新位置與舊位置的映射,且該映射是一一對(duì)應(yīng)的。下圖是一次貓臉變換的示意圖:

狹義貓臉變換示意圖

  • (a)是原圖
  • (b)是先做水平方向的錯(cuò)切
  • (c)是在(b)的基礎(chǔ)上再做一次豎直方向的錯(cuò)切
  • (d)是對(duì)圖像求模,即切割回填操作,得到變換后的圖像。

如果你想知道為什么要這樣變換,為什么是水平錯(cuò)切一個(gè)單位,豎直錯(cuò)切兩個(gè)單位:
實(shí)際上這里水平錯(cuò)切的長(zhǎng)度是一倍圖像的高度,豎直錯(cuò)切的長(zhǎng)度是一倍圖像的高度加一倍圖像的寬度。由于圖像的寬高相等,所以這里看起來(lái)是水平錯(cuò)切一個(gè)單位,豎直兩個(gè)單位。
為什么這樣子錯(cuò)切,是因?yàn)?strong>置亂的實(shí)質(zhì)是新位置與舊位置的映射,且該映射是一一對(duì)應(yīng)的。
也就是說(shuō),其它錯(cuò)切形式可能造成多個(gè)點(diǎn)移動(dòng)到同一個(gè)位置,導(dǎo)致圖像信息的丟失。例如下面兩種錯(cuò)切方式:

其他錯(cuò)切情形

第一種是水平和豎直方向都錯(cuò)切一個(gè)單位,第二種是水平一個(gè)單位,豎直三個(gè)單位。可以看出,取模后兩種錯(cuò)切方式都有部分區(qū)域重疊了。因此錯(cuò)切的單位是有一定要求的,詳見(jiàn)后文廣義的Arnold變換。

2.3 代碼實(shí)現(xiàn)

2.3.1 Java泛型的實(shí)現(xiàn)

此處寬高需要相等是方便后續(xù)的逆變換。

public class Arnold<T> {

    /**
     * 貓臉變換
     * @param origin 原始圖像
     * @param dest 用于保存變換后的圖像
     * @param count 變換的次數(shù)
     */
    public void arnold(T[][] origin, T[][] dest, int count) {
        int newY, newX;
        while (count > 0) {
            for (int row = 0; row < origin.length; row++) {
                for (int col = 0; col < origin[0].length; col++) {
                    newX = (col + row) % origin.length;
                    newY = (col + 2 * row) % origin.length;
                    dest[newY][newX] = origin[row][col];
                }
            }
            count--;
            origin = Arrays.copyOf(dest, dest.length);
        }
    }

}

2.3.2 適用于Android的一維數(shù)組形式

/**
 * 貓臉變換
 * @param origin 原始圖像,寬高必須一致
 * @param dest 用于保存輸出
 * @param SIZE 寬和高
 * @param count 變換的次數(shù)
 */
public void arnold(int[] origin, int[] dest, int SIZE, int count) {
    int oldY, oldX, newY, newX;
    while (count > 0) {
        for (int index = 0; index < origin.length; index++) {
            oldX = index % SIZE;
            oldY = index / SIZE;
            newX = (oldX + oldY) % SIZE;
            newY = (oldX + 2 * oldY) % SIZE;
            dest[newY * SIZE + newX] = origin[index];
        }
        count--;
        origin = Arrays.copyOf(dest, dest.length);
    }
}

2.3.3 實(shí)際運(yùn)行結(jié)果

如圖所示,一次變換后,原圖得到了一定程度的置亂,但還能分辨出原始圖像的信息,6次變換后圖像已看不出原始圖像的信息。


狹義貓臉變換運(yùn)行結(jié)果

3. 狹義貓臉變換的逆變換

當(dāng)一張圖片的寬度和高度相同時(shí),Arnold變換具有逆變換。雖然Arnold變換具有周期性,可以通過(guò)一直變換下去得到原圖,但是周期越長(zhǎng),恢復(fù)原圖也越長(zhǎng)。通過(guò)逆變換可以較為方便地把變換后的圖像恢復(fù)。

3.1 逆變換公式

狹義貓臉逆變換矩陣公式

轉(zhuǎn)換為多項(xiàng)式為:

狹義貓臉逆變換多項(xiàng)式公式

3.2 代碼實(shí)現(xiàn)

3.2.1 泛型形式的實(shí)現(xiàn)

/**
 * 貓臉逆變換
 * @param origin 原始圖像
 * @param dest 用于保存變換后的圖像
 * @param count 變換的次數(shù)
 */
public void inverseArnold(T[][] origin, T[][] dest, int count) {
    int newY, newX;
    while (count > 0) {
        for (int row = 0; row < origin.length; row++) {
            for (int col = 0; col < origin[0].length; col++) {
                newX = (col + row) % origin.length;
                newY = (col + 2 * row) % origin.length;
                dest[newY][newX] = origin[row][col];
            }
        }
        count--;
        origin = Arrays.copyOf(dest, dest.length);
    }
}

3.2.2 適用于Android的一維數(shù)組形式

/**
 * 貓臉逆變換
 * @param origin 原圖
 * @param dest 保存變換后的圖像
 * @param SIZE 寬高
 * @param count 變換次數(shù)
 */
public void inverseArnold(int[] origin, int[] dest, int SIZE, int count) {
    int oldY, oldX, newY, newX;
    while (count > 0) {
        for (int index = 0; index < origin.length; index++) {
            oldX = index % SIZE;
            oldY = index / SIZE;
            newY = mod((oldY - oldX), SIZE);
            newX = mod((2 * oldX - oldY), SIZE);
            dest[newY * SIZE + newX] = origin[index];
        }
        count--;
        origin = Arrays.copyOf(dest, dest.length);
    }
}

逆變換的效果當(dāng)然就是把圖像復(fù)原了。此處就不在貼效果圖了。

4. 廣義的貓臉變換

4.1 公式

如前文所述,只要錯(cuò)切的單位滿足取?;靥詈?,原圖與變換后的圖能夠一一對(duì)應(yīng),那么該變換就是有效的。滿足這個(gè)條件的公式是:

廣義貓臉變換矩陣公式.png
廣義貓臉變換行列式公式

其逆變換公式為:

廣義貓臉逆變換矩陣公式.png
廣義貓臉逆變換多項(xiàng)式公式.png

4.2 代碼實(shí)現(xiàn)

這里只列出了用于Android的一維數(shù)組形式:

4.2.1 廣義正變換

/**
 * 廣義貓臉變換
 * @param origin 原圖
 * @param dest 變換后的圖
 * @param SIZE 圖像寬度和高度
 * @param count 變換次數(shù)
 */
public void arnold(int[] origin, int[] dest, int SIZE, int count, int a, int b) {
    final int ab_plus_1 = a * b + 1;
    int oldY, oldX, newY, newX;
    while (count > 0) {
        for (int index = 0; index < origin.length; index++) {
            oldX = index % SIZE;
            oldY = index / SIZE;
            newX = (oldX + a * oldY) % SIZE;
            newY = (b * oldX + ab_plus_1 *oldY) % SIZE;
            dest[newY * SIZE + newX] = origin[index];
        }
        count--;
        origin = Arrays.copyOf(dest, dest.length);
    }
}

4.2.2 廣義逆變換

/**
 * 廣義貓臉逆變換
 * @param origin 原圖
 * @param dest 變換后的圖
 * @param SIZE 圖像寬度和高度
 * @param count 變換次數(shù)
 */
public void inverseArnold(int[] origin, int[] dest, int SIZE, int count, int a, int b) {
    final int ab_plus_1 = a * b + 1;
    int oldY, oldX, newY, newX;
    while (count > 0) {
        for (int index = 0; index < origin.length; index++) {
            oldX = index % SIZE;
            oldY = index / SIZE;
            newX = mod(ab_plus_1 * oldX - a * oldY, SIZE);
            newY = mod(oldY - b * oldX, SIZE);
            dest[newY * SIZE + newX] = origin[index];
        }
        count--;
        origin = Arrays.copyOf(dest, dest.length);
    }
}

5. 利用Arnold變換進(jìn)行加密

對(duì)于廣義Arnold變換,當(dāng)a、b、count任何一個(gè)值不同時(shí),變換后圖像也是不相同的。因此,可以把(a、b、count)作為加密參數(shù)對(duì)圖像進(jìn)行加密。此外,還可以對(duì)圖像的不同部分進(jìn)行不同的加密,使得更難破解。例如,可以把圖像分為四份(甚至可以有交集),分別對(duì)每一份子圖進(jìn)行加密,這樣又增大了破解的難度。
Arnold加密后,如果圖像被破壞了,例如壓縮、涂改等。解密后的圖像依然能恢復(fù)一部分?jǐn)?shù)據(jù)。
下圖是以參數(shù)(7,11,4)加密的圖像,以及對(duì)加密后的圖像進(jìn)行涂抹后再解密的結(jié)果。

魯棒性測(cè)試
  • (a) 原圖
  • (b) 加密后的圖像
  • (c) 涂抹
  • (d) 解謎后的圖像

可以看出Arnold變換有較高的魯棒性,即使添加了多個(gè)較大的圓也能恢復(fù)出原圖的大致信息。
根據(jù)Arnold變換的原理,我們還可以用來(lái)加密其它數(shù)據(jù),而不僅僅是圖像。

轉(zhuǎn)載須注明出處:http://www.itdecent.cn/p/39727dbaffd9

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. 概述 利用Arnold變換(又稱(chēng)貓臉變換)可以對(duì)圖像進(jìn)行置亂,使得原本有意義的圖像變成一張無(wú)意義的圖像。該變...
    Autonavi閱讀 2,268評(píng)論 0 1
  • http://blog.csdn.net/x454045816/article/details/52153250 ...
    G風(fēng)閱讀 7,371評(píng)論 0 1
  • 這些年計(jì)算機(jī)視覺(jué)識(shí)別和搜索這個(gè)領(lǐng)域非常熱鬧,后期出現(xiàn)了很多的創(chuàng)業(yè)公司,大公司也在這方面也花了很多力氣在做。做視覺(jué)搜...
    方弟閱讀 6,730評(píng)論 6 24
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,954評(píng)論 25 709
  • 凌晨,還不想睡,拿著手機(jī)開(kāi)收音機(jī)——《千里共良宵》。聽(tīng)著聽(tīng)著,豬說(shuō),原來(lái)你也聽(tīng)電臺(tái)呀,我還以為只有我和師兄聽(tīng)電臺(tái)呢...
    簡(jiǎn)福_Jane閱讀 360評(píng)論 0 0

友情鏈接更多精彩內(nèi)容