OpenCV-Python画像乗算操作cv2.multiply関数の詳細な説明とピクセル値オーバーフロー正規化処理

☞░GoにLaoYuanPythonblog░https://blog.csdn.net/LaoYuanPython

I.はじめに

OpenCV-Python画像追加操作cv2.add関数詳細説明」と「OpenCV-Python画像減算操作cv2.subtract関数詳細説明と行列減算との違い比較」に画像追加操作と減算操作の詳細紹介があります。減算は乗算と除算です。この記事では、画像の乗算について紹介します。

画像の乗算には3つのタイプがあります。詳細についてはOpenCVでの3つの乗算操作の理解と習得参照してください。最後の1つ、つまりcv2.multiply関数によって提供される乗算のみに焦点を当てます。2つの画像行列AおよびBの場合:
ここに写真の説明を挿入
この方法での乗算計算方法は次のとおりです。
ここに写真の説明を挿入

次に、画像乗算cv2.multiplyの構文

呼び出し構文:

multiply(src1, src2, dst=None, scale=None, dtype=None)

パラメータの説明:

OpenCVマニュアルで紹介されている乗算の文法的な内容は、次のように解釈されます。

  1. src1:被乗数としての画像配列
  2. src2:乗数として使用される画像配列、サイズ、タイプはsrc1と同じです。
  3. dst:オプションのパラメーター、出力結果を保存するための変数、デフォルト値はNone、Noneでない場合、出力画像はdstの対応する実際のパラメーターに保存され、そのサイズとチャネル番号は入力画像と同じです。画像の深さ(つまり、画像ピクセル)桁数)は、dtypeパラメータまたは入力画像によって決定されます
  4. scale:結果画像のオプションのスケーリング係数。つまり、src1 * src2に基づいてスケールを乗算します。
  5. マスク:イメージマスク、オプションパラメータ、8ビットシングルチャネルグレースケールイメージ。変更する出力イメージアレイの要素を指定するために使用されます。つまり、出力イメージピクセルは、マスクの対応する位置要素が0でない場合にのみ出力されます。それ以外の場合。この位置のピクセルのすべてのチャネルコンポーネントは0に設定されます
  6. dtype:オプションのパラメーター、出力画像配列の深さ、つまり、画像の単一ピクセル値のビット数(RGBが3バイトで表される場合、24ビット)。
  7. 戻り値:乗算の結果画像

3、画像乗算cv2.multiply使用シナリオ

src1とsrc2の2つの入力データに関して、OpenCVヘルプドキュメントでの乗算と加算および減算の説明が異なります。加算と減算ではスカラーを使用できますが、乗算では、2つは同じサイズとタイプである必要があります。スカラーを使用します。検証と説明のために、加算と減算のモードを参照します。

処理ケースのこの部分で使用されるソース画像は、OpenCVによって処理された複数のクラシック画像のコレクションです。画像は次のとおりです。
ここに写真の説明を挿入
画像は比較的大きく、スクリーンショットを撮るのは適切ではないため、後で画像を読み取るときに1000 * 750に調整する必要があります。

3.1、src2がスカラーの場合

画像とスカラーを乗算して観察するためのコードは次のとおりです。

import numpy as np
import cv2
def  main():
    img = cv2.resize(cv2.imread(r'F:\pic\imgs.jpg'),(1000,750))
    imgMultiply = cv2.multiply(img,1.2)
    cv2.imshow('img', img)
    cv2.imshow('imgMultiply', imgMultiply)
    cv2.waitKey(0)

main()

図に示すように、プログラムデバッグによる乗算の結果を観察し、画像を表示する前にブレークポイントを設定し、関連する変数データを監視します。
ここに写真の説明を挿入
上の黄色の部分のマトリックスチャネル値から、定数スカラーを直接乗算した後、元の画像マトリックスのピクセルの最後の2つのチャネル値は、結果の画像ではすべて0です。引き続き実行して、次のように画像を表示します。
ここに写真の説明を挿入
画像が青色であることがわかります。これは、上記の3つのチャネルの最初の青色チャネルのデータと一致しています。

3.2、src2は4倍です

前回の加算と減算の紹介では、OpenCVがスカラー演算を4倍演算に変換することを説明したので、ここでは上記の場合のスカラーを4倍に変更して検証します。コードは次のように表示されます。

def  main():
    img = cv2.resize(cv2.imread(r'F:\pic\imgs.jpg'),(1000,750))
    imgMultiply = cv2.multiply(img,(1.5,1.5,1.5,1.5))
    cv2.imshow('img', img)
    cv2.imshow('imgMultiply', imgMultiply)
    cv2.waitKey(0)

main()

追跡と観察の後、すべてのピクセルチャネルコンポーネントに1.5が乗算され、255を超える飽和動作モードが255に設定されます。表示される画像は次のとおりです。

ここに写真の説明を挿入
上の元の画像と比較すると、明らかに明るさが向上しています。実際、src2を同じ要素値の4倍に設定すると、4つの要素を1に設定し、画像を要素値に設定した場合と同等の効果が得られます。上記のコードを次のように調整します。

def  main():
    img = cv2.resize(cv2.imread(r'F:\pic\imgs.jpg'),(1000,750))
    imgMultiply = cv2.multiply(img,(1,1,1,1),scale=0.5)
    cv2.imshow('img', img)
    cv2.imshow('imgMultiply', imgMultiply)
    cv2.waitKey(0)

main()

:ズーム率の前にオプションのパラメーターdstがあるため、キーワードパラメーターフォームを使用する必要があります。
対応する結果画像は次のとおりです。画像
ここに写真の説明を挿入
の明るさが明らかに暗くなっていることがわかりますが、コントラストは変化していません。

3.1と3.2の検証条件(古いサルの検証環境はOpenCV-Python4.3.0.36、Windowsバージョン)を組み合わせると、src2は4タプルになります。乗算を使用して画像の明るさを調整する場合は、src2を4として使用できます。タプル、クォータニオンのすべての要素値は調整される輝度係数であり、スケール調整係数にすべての1つの要素を重ね合わせたクォータニオンを使用して実装することもできます。ただし、これら2つの形式はOpenCVヘルプドキュメントでは説明されていないため、現在は実行可能ですが、使用することはお勧めしません。画像の明るさを直接調整したい場合は、マトリックスとスカラーの算術乗算を直接行うことをお勧めしますが、飽和動作モードに注意する必要があります。

3.3。カラー画像配列とマスク画像配列の乗算

次のコードを使用して、カラー画像とマスク画像を乗算します。

def  main():
    img = cv2.resize(cv2.imread(r'F:\pic\imgs.jpg'),(1000,750))
    mask = np.ones(img.shape[:2],np.uint8)
    mask[100:200,100:200] = 0
    imgMultiply = cv2.multiply(img,mask,scale=0.5)

    cv2.imshow('img', img)
    cv2.imshow('imgMultiply', imgMultiply)
    cv2.waitKey(0)

main()

実行中のエラー:

"C:\Program Files\Python38\python.exe" F:/study/python/project/cvtest/cvtest.py
Traceback (most recent call last):
  File "F:/study/python/project/cvtest/cvtest.py", line 100, in <module>
    main()
  File "F:/study/python/project/cvtest/cvtest.py", line 94, in main
    imgMultiply = cv2.multiply(img,mask,scale=0.5)
cv2.error: OpenCV(4.3.0) C:\projects\opencv-python\opencv\modules\core\src\arithm.cpp:669: error: (-209:Sizes of input arguments do not match) The operation is neither 'array op array' (where arrays have the same size and the same number of channels), nor 'array op scalar', nor 'scalar op array' in function 'cv::arithm_op'

この操作は実行できないことがわかります。

3.4。カラー画像配列とカラー画像配列の乗算

次のコードを使用して、2つのカラー画像アレイの乗算演算を構築します.2番目の画像は、元の画像と同じサイズとチャネル数に基づくマトリックス画像であり、その要素値は0と1のみです。

def  main():
    img = cv2.resize(cv2.imread(r'F:\pic\imgs.jpg'),(1000,750))
    mask = np.ones(img.shape,np.uint8)
    mask[500:650,10:300] = 0
    imgMultiply = cv2.multiply(img,mask,scale=0.8)

    cv2.imshow('img', img)
    cv2.imshow('imgMultiply', imgMultiply)
    cv2.waitKey(0)

main()

実行後の結果画像のスクリーンショット:画像の
ここに写真の説明を挿入
左下隅が黒に置き換えられていることがわかります。代わりに白を使用する場合は、マスクを0に設定したチャネルをより大きな値に調整して、乗算後の飽和値が255になるようにします。といった:

def  main():
    img = cv2.resize(cv2.imread(r'F:\pic\imgs.jpg'),(1000,750))
    mask = np.ones(img.shape,np.uint8)
    mask[500:650,10:300] = 100
    imgMultiply = cv2.multiply(img,mask,scale=0.8)

    cv2.imshow('img', img)
    cv2.imshow('imgMultiply', imgMultiply)
    cv2.waitKey(0)

main()

実行結果のスクリーンショット:
ここに写真の説明を挿入
このような2つの画像を乗算することにより、結果画像のどの部分が保持され、どの部分がクリアされるかを判別できることがわかります。

3.5、カラー画像飽和操作乗算

画像自体のピクセルチャネル値は一般に0より大きいか、1より大きい数であり、画像操作は飽和操作であるため、2つの画像が乗算されるか、画像自体が乗算される場合、2つの画像のいずれかが黒くなります。結果の画像では、すべて黒であり、チャネル値の他の部分のほとんどは大幅に増加するか、飽和状態に達することさえあります。

上記の元の画像を乗算するためのコードは次のとおりです。

def  main():
    img = cv2.resize(cv2.imread(r'F:\pic\imgs.jpg'),(1000,750))
    imgMultiply = cv2.multiply(img,img)

    cv2.imshow('img', img)
    cv2.imshow('imgMultiply', imgMultiply)
    cv2.waitKey(0)

main()

自己乗算後の画像は次のようになります。
ここに写真の説明を挿入
したがって、このような2つの画像の実際の乗算は、低レベルの画像処理では基本的に無意味であり、古い猿は中高レベルの画像処理では研究されておらず、特別な目的があるかどうかは明らかではありません。

3.6。カラー画像製品のオーバーフロー処理

3.6.1、オーバーフローソリューション

画像の単一チャネル値は符号なしバイト(numpy.uint8)で表され、その値の範囲は0〜255です。画像ピクセルチャネル値が範囲を超える場合、OpenCVの飽和計算メカニズムはチャネル値を0未満に設定します。 255より大きい場合は、255に設定します。ただし、このメカニズムにより、広範囲の画像ピクセルチャネル値が255または0に設定される場合があります。たとえば、上記の3.4から、実際の2つの画像の積が、飽和した要素のために広範囲のホワイトニングを引き起こすことがわかります。

この問題を解決するには、次の方法を使用できます。

  1. 乗算する場合、画像積の結果をチャネル値uint16またはfloat32マトリックスに保存します(float32は小数を保存できるため、古い猿はfloat32を推奨します)、2つの方法があります。1つは元の入力画像マトリックスの乗算を実行することです。操作の前にfloat32マトリックスに変換します。2つ目は、元の入力イメージマトリックスが変更されず、積がfloat32イメージマトリックスに保存されることです。ただし、老猿はOpenCV-Pythonで達成する2つ目の方法を見つけられず、最初の検証のみに合格しました。入力画像をfloat32に変換します。
  2. 乗算の積行列は正規化されます。正規化については、「Opencvの正規化関数Normalize()の原理」を参照してください
3.6.2正規化処理に関するアルゴリズムの考慮事項

OpenCV-Pythonの正規化関数のNORM_MINMAXモードを使用して、マトリックス要素の値を[0,255]の範囲に戻す場合、OpenCVで使用されるアルゴリズムは次のとおりです。
ここに写真の説明を挿入

このアルゴリズムのアイデアは、元のマトリックスの最大要素値を間隔の上限(255など)にマップし、元のマトリックスの最小要素値を間隔の下限(0など)にマップすることです。他の中間値は、この値とマトリックスの最小要素値の差にマップされます。元のマトリックスの最大要素値と最小要素値の差にマッピング間隔とマッピング間隔の下限の積を掛けた比率、つまり、マッピングプロセスの線形変換は、元の要素値と元のマトリックスの最小値の差に線形変換として基づいています。要素の値を線形変換として直接取得する代わりに。

アルゴリズム的には、この方法はより科学的ですが、Lao Yuanは、画像処理の状況は特殊であると考えています。画像が暗い画像で構成されている場合、すべてのピクセルの各チャネル値が比較的大きいため、画像になります。積を[0-255]に正規化すると、差は小さくなり、画像の単一チャネルは[0-255]の間にあるため、2つの画像の積、特に自己乗算の積は、理論的には下限として0を取ります。もちろん、特定のシナリオでは正規化がより合理的である可能性があることを考慮すると、他の正規化シナリオ(画像の追加など)では、OpenCVで採用されているNORM_MINMAXモードがより合理的である可能性があります。

3.6.3、画像の乗算と正規化の処理の場合

OpenCV-Pythonの正規化とLaoYuanが検討した正規化について、乗算後の画像imgs.jpgの正規化効果の比較を実現しましょう。対応するコードは次のとおりです。

def main():
    img = cv2.imread(r'F:\pic\imgs.jpg')
    img32 = img.astype(np.float32)

    imgMultiply = cv2.multiply(img32, img32)

    imgNormalizeOpenCV = cv2.normalize(imgMultiply,None,0,255,cv2.NORM_MINMAX) #opencv归一化处理

    #老猿的归一化处理
    maxv = np.max(imgMultiply)
    imgNormalizeLaoyuan = (imgMultiply / maxv) * 255

    cv2.imshow('imgNormalizeOpenCV', imgNormalizeOpenCV.astype(np.uint8))
    cv2.imshow('imgNormalizeLaoyuan', imgNormalizeLaoyuan.astype(np.uint8))

    cv2.waitKey(0)


main()

元の画像と2つの正規化された画像を垂直方向に重ね合わせて、画像の自己乗算と正規化の効果を比較して確認しましょう。下の写真の最初の行は元の画像で、2番目の行はOpenCVによって正規化され、3番目の行は古いサルによって正規化されています。
ここに写真の説明を挿入
上の写真の比較から、自己増倍正規化処理後に画像のコントラストが増加していることがわかります。これは、自己増倍処理後に差が拡大し、正規化処理によってこの傾向が変わらないためです。同時に、2つの正規化された処理画像が同様の効果を持っていることがわかります。古い猿はデータを注意深く分析していませんでした。ほぼ同じです。これは、imgs.jpgの画像が白黒で存在するため、2つのアルゴリズムの実際の結果につながります。基本的に同じです。

4.要約:

この記事では、OpenCV-Python画像乗算操作cv2.multiply関数の呼び出し構文を詳細に紹介し、OpenCV乗算と画像オーバーフローの正規化のいくつかの使用シナリオを分析します。これらの分析を通じて、OpenCV画像乗算操作には3つの主要なタイプがあることがわかります。効果:

  1. 画像とスカラー乗算により、画像の明るさを調整できます。
  2. 画像とマスクの乗算により、出力画像の範囲を制御できます。
  3. 画像の自己乗算により、画像のコントラストを調整できます。

OpenCV-Pythonの詳細については、「OpenCV-Pythonグラフィックスと画像処理」の列を参照してください。

ブログアドレスhttps//blog.csdn.net/laoyuanpython/category_9979286.html

古い猿についての有料コラム

Lao Yuanの有料コラム「PyQtを使用したグラフィカルインターフェースPythonアプリケーションの開発」(https://blog.csdn.net/laoyuanpython/category_9607725.html)では、PythonベースのPyQtグラフィカルインターフェース開発の基本的なチュートリアルと、有料コラム「映画のようなオーディオとビデオの開発」を具体的に紹介しています。コラム」(https://blog.csdn.net/laoyuanpython/category_10232926.html)では、映画のようなオーディオとビデオの編集と合成の関連する方法と、関連する編集と合成のシーンを処理するための関連する方法の使用について詳しく紹介しています。どちらのコラムも特定のシーンに適しています。基本的なPythonを持っているが、関連する知識がない初心者の読者は学びます。

有料コラム記事ディレクトリ:「moviepyオーディオおよびビデオ開発コラム記事ディレクトリ」(https://blog.csdn.net/LaoYuanPython/article/details/107574583)、「PyQtを使用してグラフィカルインターフェイスPythonアプリケーションコラムディレクトリを開発する」(https:// blog.csdn.net/LaoYuanPython/article/details/107580932)。

Pythonの基礎が不足している場合は、Lao Yuanの無料のコラム「Column:Python Basic Tutorial Directory」(https://blog.csdn.net/laoyuanpython/category_9831699.html)からPythonを最初から学ぶことができます

Old Apeの読者に興味があり、喜んでサポートする場合は、有料のコラムを購入することを歓迎します。

古い猿からPythonとOpenCVを学びましょう!

☞░LaoYuanPythonブログ投稿ディレクトリhttps://blog.csdn.net/LaoYuanPython░に移動します

おすすめ

転載: blog.csdn.net/LaoYuanPython/article/details/109105916