第 3 章: 画像の操作

画像加算ビット演算は比較的基本的な演算です。しかし、多くの複雑な画像処理機能は、これらの基本操作を利用して完了します。例: ビットプレーン分解、画像 XOR 暗号化、電子透かしなど。

1. 画像追加操作:

画像処理では、多くの場合、画像に対して加算操作を実行する必要があります。画像はプラス演算子「+」で追加することも、cv2.add() 関数で追加することもできます。

  • プラス演算子「+」
  • cv2.add()

通常、グレースケール画像ではピクセルは 8 ビット (1 バイト) で表され、ピクセル値の範囲は [0, 255] です。2 つのピクセル値を加算すると、合計は 255 を超える可能性があります。上記 2 つの加算方法は、255 を超える値の処理方法が異なります。

1. プラス演算子「+」:

プラス演算子「+」を使用して、次の規則に従ってイメージ a (ピクセル値 a) とイメージ b (ピクセル値 b) を合計します。

a + b = { a + b , a + b ≤ 255 mod ( a + b , 256 ) , a + b > 255 a+b = \begin{cases} a +b, \quad a+b≤255 \\ mod(a+b, 256), \quad a+b >255 \end{件}ある+b={ ある+b ある+b2 5 5mod ( a _ _+b 2 5 6 ) ある+b 2 5 5

式中、mod(): 剰余演算 mod(a + b, 256) は、「a+b」の和を計算し、256 で割って余りを求めることを意味します。

上記の規則に従って、2 つのピクセルが追加されると、次のようになります。

  • 2 つの画像の対応するピクセル値の合計が 255 以下の場合は、それらを直接加算して演算結果を取得します。例: 28 と 36 を足して 64 を得る
  • 2 つの画像の対応するピクセル値の合計が 255 より大きい場合、演算結果はモジュロ 256 になります。例: 255+58 = 313 の場合、計算結果は (255+58) % 256 = 57 となります。

例:乱数の配列を使用してグレースケール画像をシミュレートし、「+」を使用してピクセル値を合計した結果を観察します。

注: 配列の型を dtype = np.uint8 として定義すると、配列値の範囲が [0, 255] の間になることが保証されます。

import numpy as np

img1 = np.random.randint(0, 256, size=[3, 3], dtype=np.uint8)
img2 = np.random.randint(0, 256, size=[3, 3], dtype=np.uint8)

print('img1=\n', img1)
print('img2=\n', img2)
print('img1+img2=\n', img1+img2)

結果:

img1=
 [[241  85  79]
 [ 62  29 113]
 [ 33 129 150]]
img2=
 [[168  93 112]
 [ 32 246 228]
 [229  89 107]]
img1+img2=
 [[153 178 191]
 [ 94  19  85]
 [  6 218   1]]

: この例では、加算の法は配列型 dtype=np.uint8 によって実行されます。

2. cv2.add() 関数:

関数 cv2.add() を使用すると、画像のピクセル値の合計を計算できます。構文形式は次のとおりです。

  • 結果 = cv2.add(a, b)

cv2.add() を使用してピクセル値 a と b を合計する場合は、次の規則に従います: a + b = { a + ba + b ≤ 255 255 a + b > 255 a + b = \begin{cases} a + b \quad a + b≤255 \\ 255 \quad a+b>255 \end{件}ある+b={ ある+bある+b2 5 52 5 5ある+b 2 5 5

cv2.add() のパラメータには次の 3 つの形式があります。

  • resutl = cv2.add(image 1, image 2): どちらのパラメータも画像であり、操作に参加する画像のサイズとタイプは一貫している必要があります
  • result = cv2.add(value, image): 第一引数は値、第二引数は画像 このとき、画像の彩度値を超える値は最大値まで処理されます。
  • result = cv2.add(image, value): 第一パラメータは画像、第二パラメータは値 このとき画像の彩度値を超える値は最大値まで処理されます。

例:プラス演算子と関数 cv2.add() を使用して、2 つのグレースケール イメージのピクセル値の合計を計算します。

import cv2
a = cv2.imread('../lena.bmp', 0)
b = a
result1 = a + b
resutl2 = cv2.add(a, b)
cv2.imshow('original', a)
cv2.imshow('result1', result1)
cv2.imshow('result2', resutl2)
cv2.waitKey()
cv2.destroyAllWindows()

ここに画像の説明を挿入

処理結果から次のことがわかります。

  • プラス演算子を使用します。255 を超える合計に対しては係数演算のみが実行されます。係数の後、255 を超える値の部分が小さくなり、明るいはずの点が暗くなります。
  • cv2.add()関数を使用します。255より大きい値を彩度値255として処理します。画像のピクセル値が増加し、画像全体が明るくなります。

2. 画像加重合計:

いわゆる画像加重和とは、2 つの画像のピクセル値の合計を計算するときに各画像の重みを考慮することです。これは次のように表すことができます: dst = saturate ( src 1 × α + src 2 × β + γ ) dst = 飽和(src1×\alpha + src2×\beta + \gamma)d s t=飽和状態( s r c 1 _ _ _ _ _ _×ある+s r c 2×b+c )

式中の stautrate() は彩度の値を取得することを意味します。画像の重み付けと計算を行う場合、src1 と src2 は同じサイズとタイプである必要がありますが、特定のタイプとチャネルについては特別な制限はありません。任意のデータ型を使用でき、任意の数のチャネルを含めることができます。(グレースケール画像またはカラー画像) それらが同じである限り。

OpenCVでは関数cv2.addWeighted()を利用して画像の加重加算演算(混合・融合)を実現しています。

文法形式:

  • dst = cv2.addWeighted(src1, alpha, src2, beta, gamma)

    このうち、パラメータ alpha と beta は src1 と src2 に対応する係数で、その合計が 1 になる場合もあれば、1 に等しくない場合もあります。 この関数で実現される関数は、dat = src1 x alpha + src2 x beta + gamma となります。式内のパラメータ gamma は 0 にすることもできますが、このパラメータは必須であり、省略できないことに注意してください。上式は「結果=画像1×係数1+画像2×係数2+明るさ調整量」と理解できます。

例 1:配列を使用して、関数 cv2.addWeighted() の使用法を示します。

import cv2
a = cv2.imread('../lena.bmp')
b = cv2.imread('../boat.512.tiff')
result = cv2.addWeighted(a, 0.6, b, 0.4, 0)
cv2.imshow('lena', a)
cv2.imshow('boat', b)
cv2.imshow('result', result)
cv2.waitKey()
cv2.destroyAllWindows()

ここに画像の説明を挿入

3. ビット単位の論理演算:

論理演算は非常に重要な演算方法であり、画像処理ではビット単位で論理演算を行うことが多いですが、ここではOpenCVにおけるビット単位の論理演算(ビット演算)について説明します。

OpenCV の一般的なビット操作関数:

ここに画像の説明を挿入

1. ビット単位の AND 演算:

AND 演算では、AND 演算に含まれる両方の論理値が true の場合、結果は true になります。その論理関係は、下図の直列回路と比較できます。両方のスイッチが閉じている場合にのみ点灯します。

ここに画像の説明を挿入

ここに画像の説明を挿入

OpenCV では、 cv2.bitwise_and() 関数を使用してビットごとの AND 演算を実装できます。その構文形式は次のとおりです。

  • dst = cv2.bitwise_and(src1, src2[, マスク])

式では次のようになります。

  • dst: 入力値と同じサイズの配列出力値を示します。
  • src1: 配列またはスカラー型の最初の入力値を示します。
  • src2: 2 番目の配列またはスカラー型の入力値を示します。
  • マスク: オプションの演算マスク、8 ビットの単一チャネル配列を示します。

注:ビット単位の AND 演算には次の特徴があります。

  • 任意の値 N と値 0 に対してビット単位の AND 演算を実行すると、値 0 が得られます。
  • 任意の値 N (ここでは 8 ビット値のみを考慮します) と値 255 (8 ビット 2 進数で 1111111) をビットごとに AND 演算すると、値 N そのものが得られます。

ここに画像の説明を挿入

例 1:ビットごとの AND 演算を使用して、マスクで指定されたイメージの部分を保持する、マージされたイメージを構築します。

import cv2
import numpy as np
a = cv2.imread('../lena.bmp', 0)
b = np.zeros(a.shape, dtype=np.uint8)
b[100: 400, 200: 400] = 255
b[100: 500, 100: 200] = 255

c = cv2.bitwise_and(a, b)
cv2.imshow('a', a)
cv2.imshow('b', b)
cv2.imshow('c', c)
cv2.waitKey()
cv2.destroyAllWindows()

ここに画像の説明を挿入

注: グレースケール イメージのマスクに加えて、BGR モードでカラー イメージの指定された部分を抽出するためにマスクを使用することが必要になることがよくあります。ビット単位の AND 演算では、演算に含まれるデータが同じチャネルを持つ必要があるため、カラー画像と単一チャネルのマ​​スク画像に対してビット単位の AND 演算を直接実行することは不可能です。一般に、マスク演算は、BGR モードでマスク画像をカラー画像に変換し、カラー画像とマスク画像のビット単位の AND 演算を実行することで実現できます。

import cv2
import numpy as np
a = cv2.imread('../lena512color.tiff', 1)
b = np.zeros(a.shape, dtype=np.uint8)
b[100: 400, 200: 400] = 255
b[100: 500, 100: 200] = 255

c = cv2.bitwise_and(a, b)
cv2.imshow('a', a)
cv2.imshow('b', b)
cv2.imshow('c', c)
cv2.waitKey()
cv2.destroyAllWindows()

ここに画像の説明を挿入

2. ビット単位の OR 演算:

OR 演算のルールは、演算に含まれる 2 つの論理値のいずれかが true の場合に結果が true になるということです。以下に示すような並列回路:

ここに画像の説明を挿入

ここに画像の説明を挿入

OpenCV では、 cv2.bitwise_or() 関数を使用してビットごとの OR 演算を実装できます。その構文形式は次のとおりです。

  • dst = cv2.bitwise_or(src1, src2, [, マスク])

式では次のようになります。

  • dst: 入力値と同じサイズの配列出力値を示します。
  • src1: 配列またはスカラー型の最初の入力値を示します。
  • src2: 2 番目の配列またはスカラー型の入力値を示します。
  • マスク: オプションの演算マスク、8 ビットの単一チャネル配列を示します。

ここに画像の説明を挿入

3. ビット単位の NOT 演算:

NOT 演算は否定演算です。

  • オペランドが true の場合、結果は false になります。
  • オペランドが false の場合、結果は true になります

ここに画像の説明を挿入

ビット単位の NOT 演算とは、値を 2 進値に変換した後、対応する位置に対して NOT 演算を実行することを指します。

OpenCV では、関数 cv2.bitwise_not() を使用してビットごとの反転演算を実現できます。その構文形式は次のとおりです。

  • dst = cv2.bitwise_not(src, [マスク])

式では次のようになります。

  • dst: 入力値と同じサイズの配列出力値を示します。
  • src1: 配列またはスカラー型の最初の入力値を示します。
  • マスク: オプションの演算マスク、8 ビットの単一チャネル配列を示します。

ここに画像の説明を挿入

4. ビット単位の XOR 演算:

XOR演算は半加算演算とも呼ばれ、そのアルゴリズムは2進ビットを持たない加算に似ており、英語名は「exclusive OR」であるため、通常はxorと表現されます。

ここに画像の説明を挿入

ビット単位の XOR 演算とは、値をバイナリ値に変換した後、対応する位置に対して XOR 演算を実行することを指します。

ここに画像の説明を挿入

OpenCV では、関数 cv2.bitwise_xor() を使用してビットごとの反転演算を実現できます。その構文形式は次のとおりです。

  • dst = cv2.bitwise_xor(src1, src2, [マスク])

式では次のようになります。

  • dst: 入力値と同じサイズの配列出力値を示します。
  • src1: 配列またはスカラー型の最初の入力値を示します。
  • src2: 2 番目の配列またはスカラー型の入力値を示します。
  • マスク: オプションの演算マスク、8 ビットの単一チャネル配列を示します。

4.マスク:

OpenCV の多くの関数は、マスクとも呼ばれるマスクを指定します。次に例を示します。

結果 = cv2.add(パラメータ 1、パラメータ 2、マスク)

マスク パラメーターを使用する場合、操作はマスク値が空ではないピクセルに対してのみ実行され、他のピクセルは 0 に設定されます。

例1:

画像 1 = ∣ 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 ∣ 画像 2 = ∣ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 ∣ マスク = ∣ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 ∣ image1 = \begin{vmatrix} 3 & 3 & 3 & 3 & 3 \\ 3 & 3 & 3 & 3 & 3 \\3 & 3 & 3 & 3 & 3 \\3 & 3 & 3 & 3 & 3 \\3 & 3 & 3 & 3 & 3 \ end{vmatrix} \quad image2 = \begin{vmatrix} 5 & 5 & 5 & 5 & 5 \\ 5 & 5 & 5 & 5 & 5 \\5 & 5 & 5 & 5 & 5 \\5 & 5 & 5 & 5 & 5 \\5 & 5 & 5 & 5 & 5 \end{vmatrix} \quadマスク= \begin{vmatrix} 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\0 & 0 & 0 & 0 & 0 \\0 & 0 & 0 & 1 & 1 \\0 & 0 & 0 & 1 & 1\end{vmatrix}画像1 _ _ _ _=3333333333333333333333333画像2 _ _ _ _=5555555555555555555555555m a k _=0000000000000000001100011

img3 = cv2.add(img1, img2, mask=mask)画像 3 は操作後に取得されます。

img 3 = ∣ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 0 0 8 8 ∣ img3= \begin{vmatrix} 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\0 & 0 & 0 & 0 & 0 \\0 & 0 & 0 & 8 & 8 \\0 & 0 & 0 & 8 & 8 \end{vmatrix}3です=0000000000000000008800088

img3 は計算す​​る際、マスクマスクの制御のもと「img1 + img2」の結果を計算します。計算中はマスク1の部分が「img1+img2」に相当し、その他の部分の画素値は全て0となります。

知らせ:

マスクは画像の加算演算だけでなく、ビット演算などの他の演算でも使用されます。

前のビット演算では、カラーの元の画像とマスク画像を計算しましたが、ビット単位の AND 演算では、演算に含まれるデータが同じチャネルを持つ必要があるため、カラー画像と単一の画像を直接実行することは不可能です。チャネルマスクイメージ、ビット単位の AND 演算。BGR モードでマスク画像をカラー画像に変換し、カラー画像と (カラー) マスク画像に対してビットごとの AND 演算を実行してマスク演算を実現する必要があります。

実際、関数で使用されるマスク パラメーターは 8 ビットのシングル チャネル イメージにすることができます。したがって、マスク イメージをビットごとの AND 関数 cv2.bitwise_and(src1, src2 [,マスク]) のパラメーター マスクの値として使用して、マスク操作を完了できます。このとき、関数 cv2.bitwise_and(src1, src2 [,mask]) のパラメータ src1 と src2 として処理対象のカラー画像を同時に使用し、マスク画像をマスクパラメータとして使用して完了します。ビットごとの AND 演算により、メンブレン コントロールのマスク カラー イメージを取得できます。

補足:いかなる数値やブリーディングもビット単位で計算され、結果はそのままです。

import cv2
import numpy as np

img1 = cv2.imread('../lena512color.tiff')
w, h, c = img1.shape
mask = np.zeros((w, h), dtype=np.uint8)
mask[100: 400, 200: 400] = 255
mask[100: 500, 100: 200] = 255
img2 = cv2.bitwise_and(img1, img1, mask=mask)
cv2.imshow('img1', img1)
cv2.imshow('mask', mask)
cv2.imshow('img2', img2)
cv2.waitKey()
cv2.destroyAllWindows()

ここに画像の説明を挿入

5. 画像および数値演算:

前述の加算演算やビット演算では、演算に関わるパラメータは同じであり、実際には 2 つの画像、または 1 つの画像と 1 つの値の場合があります。

例: 画像全体の明るさを上げたい場合は、各ピクセル値に特定の値を追加できます。実装中に、均一なピクセル値を持つ画像を画像に追加することも、固定値を画像に追加することもできます。

例 1: img1 と img2 の元の値は次のとおりです。

画像 1 = ∣ 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 ∣ 画像 2 = ∣ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 ∣ image1 = \begin{vmatrix} 3 & 3 & 3 & 3 & 3 \\ 3 & 3 & 3 & 3 & 3 \\3 & 3 & 3 & 3 & 3 \\ 3 & 3 & 3 & 3 & 3 \\3 & 3 & 3 & 3 & 3 \end{vmatrix} \quad image2 = \begin{vmatrix} 5 & 5 & 5 & 5 & 5 \\ 5 & 5 & 5 & 5 & 5 \\5 & 5 & 5 & 5 & 5 \\5 & 5 & 5 & 5 & 5 \\5 & 5 & 5 & 5 & 5 \end{vmatrix}画像1 _ _ _ _=3333333333333333333333333画像2 _ _ _ _=5555555555555555555555555

  • img3 = cv2.add(img1, img2) 操作の後、img3 は次のように取得されます。

画像 3 = ∣ 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 ∣ 画像 3 = \begin{vmatrix} 8 & 8 & 8 & 8 & 8 \\ 8 & 8 & 8 & 8 & 8 \\8 & 8 & 8 & 8 & 8 \\8 & 8 & 8 & 8 & 8 \\8 & 8 & 8 & 8 & 8 \end{vmatrix}画像3 _ _ _ _=8888888888888888888888888

  • img4 = cv2.add(img1, 6) 演算の後、img4 は次のように取得されます。

画像 4 = ∣ 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 ∣ 画像 4 = \begin{vmatrix} 9 & 9 & 9 & 9 & 9 \\ 9 & 9 & 9 & 9 & 9 \\9 & 9 & 9 & 9 & 9 \\9 & 9 & 9 & 9 & 9 \\9 & 9 & 9 & 9 & 9 \end{vmatrix}画像4 _ _ _ _=9999999999999999999999999

  • img5 = cv2.add(6, img1) 操作の後、取得される img5 は次のようになります。

画像 5 = ∣ 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ∣ image5 = \begin{vmatrix} 11 & 11 & 11 & 11 & 11 \\ 1 1& 11 & 11 & 11 & 11 \\11 & 11 & 11 & 11 & 11 \\11 & 11 & 11 & 11 & 11 \\11 & 11 & 11 & 11 & 11 \end{vmatrix}画像5 _ _ _ _=1 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 1

6. ビットプレーンの分解:

グレースケール イメージ内の同じビット内のバイナリ ピクセルを結合して、グレースケール イメージのビット プレーンと呼ばれる新しいバイナリ イメージを取得します。このプロセスはビットプレーン分解と呼ばれます。たとえば、「最下位ビット」ビット プレーンは、グレースケール イメージ内のすべてのピクセルの最低値を組み合わせて形成できます。

8 ビット グレースケール画像では、各ピクセルは 8 ビット バイナリで表され、その値の範囲は [0, 255] の間です。値は次のように表現できます。

ここに画像の説明を挿入

式中, a i a_i ある私は0 または 1 のみの場合があります。それぞれのai a_iがわかります。ある私は重みは同じではありません、7 a_7ある7最も高い重みを持つa 0 a_0ある0体重が最も軽いです。これは7 a_7を表しますある7の値は画像に最も大きな影響を与えますが、0 a_0ある0値 0 は、イメージへの影響が最も少なくなります。

グレースケール画像の画素の2値画素値の各ビットの組み合わせを抽出することにより、複数のビットプレーン画像を得ることができる。画像内のすべてのピクセル値のai a_iある私はこの値によって構成されるビットプレーンを第 i ビットプレーン (第 i 層) と呼びます。8 ビット グレースケール イメージでは、8 つのバイナリ イメージを構成できます。つまり、元のイメージを 8 ビット プレーンに分解できます。

上記の分析によると、各ai a_iのピクセル値はある私は重みは同じではありません:

  • a7 a_7ある7重みが最も高く、結果のビット プレーンは元の画像との相関が最も高く、通常、変更されたビット プレーンは元の画像に最も似ています。
  • a0a_0ある0重みが最も低い場合、結果として得られるビット プレーンは元のイメージとの相関が最も低くなり、通常、プレーンは乱雑に見えます。

ビットプレーンの分解は、ビ​​ットごとの AND 演算を使用して実現できます。たとえば、ピクセル値が次のようなグレースケール画像 O があります。

ここに画像の説明を挿入

対応するバイナリ値は次のとおりです。

ここに画像の説明を挿入

すべてのピクセルのai a_iある私は値を組み合わせて画像の 8 ビット プレーンを取得します。ああ、一度はa 0 − a 7 a_0 - a_7ある0ある7

ここに画像の説明を挿入

RGB画像の場合、Rチャネル、Gチャネル、Bチャネルの各チャネルに対応するビットプレーンを結合すると、新たなRGBカラー画像を形成できます。たとえば、RGB 画像の場合、R チャネルの 3 番目のビット プレーン、G チャネルの 3 番目のビット プレーン、B チャネルの 3 番目のビット プレーンが結合されて、新しい RGB カラー画像が形成されます。これを 3 番目と呼びます。元の画像のビットプレーン。以上の方法により、カラー画像のビットプレーン分解を完了することができる。

グレースケール イメージを例として、ビット プレーン分解の具体的な手順を紹介します。

  1. 画像の前処理: 元の画像 O を読み込み、元の画像の幅 M と高さ N を取得します。

  2. 抽出行列を構築します。ビットごとの AND 演算を使用して、値の指定されたビットの数値を簡単に抽出します。たとえば、次の図では、さまざまな抽出係数 F を使用して、値 N の特定のビットを抽出します。
    ここに画像の説明を挿入

    上記の解析結果によれば、値は2 n 2^nであることがわかります。2nの Matは、元の画像とのビットごとの AND 演算の抽出行列として使用され、n 番目のビット プレーンが抽出されます。

    抽出された行列 Mat の値は次のようになります。
    ここに画像の説明を挿入

  3. ビットプレーンを抽出します。

    グレースケール イメージと抽出行列に対してビット単位の AND 演算を実行して、個々のビット プレーンを取得します。

    ピクセル値を2 n 2^nの値と比較します2ビット単位の AND 演算はnの値に対して実行され、これによりピクセル値の n 番目のビットが変更されないことが保証され、残りのビットが 0 に設定されます。したがって、画素値と特定値とのビット単位のAND演算により、画素値の特定の2進ビットの値を抽出することができる。同様に、ビット単位の演算を通じて、画像の指定されたビット プレーンを抽出できます。

    例えば、画素値が219の画素があった場合、その2進数の4ビット目の値、つまり画素値の4ビット目の情報(シリアル番号は0から始まる)を抽出する必要がある。この時点で、使用する必要がある抽出値は「2 4 2^4 」です。24 = 16 インチ。
    ここに画像の説明を挿入

    例えば:

    次の図のイメージ O のビット プレーンを抽出します。

    ここに画像の説明を挿入

    対応するバイナリ形式は次のとおりです。

    ここに画像の説明を挿入

    3 番目のビットプレーンを抽出するには、2 3 2^3の要素値を確立する必要があります23 (8) 抽出行列:

    ここに画像の説明を挿入

    元の画像と抽出行列に対してビットごとの AND 演算を実行して、次を取得します。
    ここに画像の説明を挿入

    補足:抽出されたビットプレーンは、2 値のピクセル値を指定されたビットだけ右にシフトし、モジュロ 2 することによっても取得できます。たとえば、n 番目のビット プレーンを抽出するには、ピクセルを右に n ビット移動し、モジュロ 2 を実行して n 番目のビット プレーンを取得します。

  4. しきい値:

    計算されたビットプレーンは2値画像(つまり0値と特定の値)であり、上記で得られたビットプレーンをそのまま表示するとほぼ黒の画像が得られます。現在の表示は 8 ビットのグレースケール画像であるため、ピクセル値が小さい場合、表示される画像はほぼ黒になります。

    つまり、毎回ビットプレーンを抽出した後、バイナリビットプレーンを白黒で表示したい場合は、取得したバイナリビットプレーンを閾値化し、0から255以外の数値を設定する必要があります。

  5. 表示画像:

例: 画像のビットプレーンを抽出します。

import cv2
import numpy as np

lena = cv2.imread('../lena.bmp', 0)
cv2.imshow('lena', lena)
r, c = lena.shape
x = np.zeros((r, c, 8), dtype=np.uint8)
for i in range(8):
    x[:, :, i] = 2**i
r = np.zeros((r, c, 8), dtype=np.uint8)
for i in range(8):
    r[:, :, i] = cv2.bitwise_and(lena, x[:, :, i])
    mask = r[:, :, i] > 0
    r[mask] = 255
    cv2.imshow(str(i), r[:, :, i])
cv2.waitKey()
cv2.destroyAllWindows()

ここに画像の説明を挿入

7. 画像の暗号化と復号化:

画像の暗号化と復号化は、画像のビット単位の XOR 演算を通じて実現できます。

暗号化は元の画像とキー画像をビットごとに XOR 演算することで実現でき、復号は暗号化された画像とキー画像を再度ビットごとに XOR 演算することで実現できます。

ここに画像の説明を挿入

XOR 演算の規則によれば、次のことが想定されます。

  • xor(a, b) = c

次に、次のものを取得できます。

  • xor(c, b) = a

  • xor(c, a) = b

ビットごとの XOR プロセスの例:

ここに画像の説明を挿入

上記の結果から、a、b、c には次の関係があります。

  • a: 平文、生データ
  • b:キー
  • c: xor(a, b) によって実現される暗号文

この場合、異議申し立てデータの操作は次のように理解できます。

  • 暗号化プロセス: 平文 a と鍵 b のビットごとの XOR を実行して暗号化を完了し、暗号文 c を取得します。
  • 復号化プロセス: 暗号文 c と鍵 b のビットごとの XOR を実行して復号化を完了し、平文 a を取得します。

ビット演算とは2値のビットに対する演算のことで、ビット演算を利用することで画素の暗号化や復号化を実現できます。

画像処理のプロセスでは、通常、処理される画像ピクセルの値はグレー値であり、その方向は [0, 255] です。たとえば、特定のピクセルの値が 216 (平文) の場合、178 (この値は暗号化プログラムによって定義されます) を暗号化のキーとして使用し、これら 2 つの数値のバイナリ値を XOR 演算します。つまり、暗号化が完了し、暗号文106が得られる。復号化が必要な場合、暗号文106と鍵178はビットごとのXOR演算を受けて、元のピクセルの値216が得られる。

  • bit_xor(216, 178) = 106
  • bit_xor(106, 178) = 216

暗号化プロセス:

ここに画像の説明を挿入

復号化プロセス:

ここに画像の説明を挿入

画像の各ピクセルに対して上記の操作を繰り返して、画像の暗号化と復号化の操作を完了します。

例:元の画像を暗号化するキーとして画像をランダムに生成する

import cv2
import numpy as np

lena = cv2.imread('../lena.bmp', 0)
r, c = lena.shape
key = np.random.randint(0, 256, size=[r, c], dtype=np.uint8)
encryption = cv2.bitwise_xor(lena, key)
decryption = cv2.bitwise_xor(encryption, key)
cv2.imshow('lena', lena)
cv2.imshow('key', key)
cv2.imshow('encryption', encryption)
cv2.imshow('decryption', decryption)

cv2.waitKey()
cv2.destroyAllWindows()

ここに画像の説明を挿入

8. 電子透かし:

最下位ビット値はバイナリ値の 0 番目のビット、つまり最下位ビットです。最下位ビット情報の隠蔽とは、隠す必要があるバイナリ画像情報をキャリア画像の最下位ビットに埋め込むことを指します。つまり、キャリア画像の最下位ビットを、隠す必要がある現在のバイナリ画像に置き換えます。の目標を隠したバイナリ画像を実現するために。バイナリ画像はキャリアの最下位ビットにあるため、キャリア画像に明らかな影響を与えず、隠蔽性が高くなります。

この情報の隠蔽は電子透かしとも呼ばれます。このようにして、次のことが可能になります。

  • 情報隠蔽
  • 著作権認証
  • 認証

などの機能を利用する場合、電子透かし情報はテキスト、ビデオ、オーディオなどの形式にすることができます。

1. 原則:

ビットプレーンの観点から見ると、電子透かしは次の 2 つの部分に分けられます。

  • 埋め込み処理:キャリア画像の0ビットプレーンに電子透かし情報(2値画像)を埋め込みます。

    たとえば、グレースケール画像は次のようになります。

    ここに画像の説明を挿入

    対応するバイナリは次のとおりです。

    ここに画像の説明を挿入

    グレースケール バイナリ イメージ W があります。

    ここに画像の説明を挿入

    グレースケールのバイナリ透かし画像 W を埋め込むと、次のようになります。

    ここに画像の説明を挿入

    情報の最下位ビットは値のサイズに限定的な影響を与えるため、画像は大幅に変形されず、肉眼では見えません。

    ここでは理解を容易にするためにキャリア画像がグレースケール画像の場合のみを紹介しますが、実際には複数のチャネルに同じウォーターマークを埋め込んだり(ロバスト性を高めるため)、異なるチャネルに異なるウォーターマークを埋め込んだりすることもできます(堅牢性を高めるため)。埋め込みを改善する)、量)など。

    • 注: 実際の処理プロセスでは、元の画像と透かし画像がカラー画像である場合がありますが、このとき、最初にチャネルとレイヤーごとに分解する必要があります。次に、電子透かしをキャリア画像に埋め込みます。
  • 抽出処理:キャリア画像の0番目のビットプレーンを抽出して電子透かしを取得します。

    抽出プロセスは、埋め込みプロセスの逆です。

2.実施方法:

最小有限ビットウォーターマークの実装には埋め込み処理と抽出処理があり、具体的な実装方法を以下に紹介します。

埋め込みプロセス:

  1. キャリア画像の前処理: 元のキャリア画像を読み取り、キャリア画像の行番号 M と列番号 N を取得します。

  2. 抽出行列を作成する: サイズが MxN、要素値が 254 の抽出行列を作成します。画像の上位 7 ビットを抽出するために使用されます

  3. ビット単位の AND 演算により、キャリア画像の上位 7 ビットが抽出され、最下位ビットが 0 に設定されます。

  4. 透かし画像処理: 場合によっては、透かし画像に対して簡単な処理を行う必要がある場合があります。たとえば、透かし画像が 8 ビット グレースケール画像の 2 値画像である場合、透かし画像を 2 値の 2 値画像に変換する必要があります。キャリアイメージの最下位ビットへの埋め込みを容易にします。
    ここに画像の説明を挿入

  5. 透かしの埋め込み: 元のキャリア画像に「上位 7 ビットを予約し、最下位の位置は 0」の操作を行った後、新しい画像を取得し、新しい画像と透かし画像に対してビットごとの OR 演算を実行して、透かし情報をキャリア画像に埋め込みます。

  6. 画像表示:上記の操作が完了すると、オリジナル画像、透かし画像、透かし画像を表示できるようになります。
    ここに画像の説明を挿入

抽出プロセス:

  1. 透かし入りキャリア画像処理: 透かし入りキャリア画像を読み取り、透かし入りキャリア画像のサイズ MxN を取得します。
  2. 抽出行列を作成する: サイズが MxN、値が 1 の抽出行列を使用することをお勧めします。
  3. 透かし情報の抽出: 透かしを含むキャリア画像と抽出行列に対してビット単位の AND 演算を実行して、透かし情報を抽出します。
  4. 透かしを除去した後のキャリア画像を計算する
  5. 表示画像
    ここに画像の説明を挿入

注: ピクセル値の最下位ビットは、ピクセル値のモジュロ 2 を取得することで取得できます。したがって、最下位ビットの透かし情報は、画素値の2を法とすることにより取得できる。

例:模擬電子透かしの埋め込み・抽出処理

import cv2
import numpy as np

lena = cv2.imread('../lena.bmp', 0)
watemark = cv2.imread('../boat.512.tiff', 0)
w = watemark[:, :] > 0
watemark[w] = 1

r, c = lena.shape
t254 = np.ones((r, c), dtype=np.uint8) * 254
lena_h7 = cv2.bitwise_and(lena, t254)
e = cv2.bitwise_or(lena_h7, watemark)
t1 = np.ones((r, c), dtype=np.uint8)
wm = cv2.bitwise_and(e, t1)

w = wm[:, :] > 0
wm[w] = 255
cv2.imshow('lena', lena)
cv2.imshow('watemake', watemark*255)
cv2.imshow('e', e)
cv2.imshow('wm', wm)
cv2.waitKey()
cv2.destroyAllWindows()

注: ピクセル値の最下位ビットは、ピクセル値のモジュロ 2 を取得することで取得できます。したがって、最下位ビットの透かし情報は、画素値の2を法とすることにより取得できる。

例:模擬電子透かしの埋め込み・抽出処理

import cv2
import numpy as np

lena = cv2.imread('../lena.bmp', 0)
watemark = cv2.imread('../boat.512.tiff', 0)
w = watemark[:, :] > 0
watemark[w] = 1

r, c = lena.shape
t254 = np.ones((r, c), dtype=np.uint8) * 254
lena_h7 = cv2.bitwise_and(lena, t254)
e = cv2.bitwise_or(lena_h7, watemark)
t1 = np.ones((r, c), dtype=np.uint8)
wm = cv2.bitwise_and(e, t1)

w = wm[:, :] > 0
wm[w] = 255
cv2.imshow('lena', lena)
cv2.imshow('watemake', watemark*255)
cv2.imshow('e', e)
cv2.imshow('wm', wm)
cv2.waitKey()
cv2.destroyAllWindows()

この記事の内容は書籍『OpenCV かんたん入門』から要約したものですので、詳しくは本書を参照してください。

おすすめ

転載: blog.csdn.net/weixin_57440207/article/details/121103553