opencvラーニング13:画像ピラミッドと画像勾配

1.スケール調整

    名前が示すように、ソース画像のサイズは拡大または縮小されます。サイズ変更機能をopencvで使用すると、ソース画像を指定されたサイズのターゲット画像に正確に変換できます。画像を縮小するには、CV_INETR_AREA(面積補間)を使用して補間することをお勧めします画像を拡大するには、CV_INTER_LINEAR(線形補間)を使用することをお勧めしますこの関数は、単純な画像スケーリングを行うために使用できます。次の画像ピラミッドは非常に便利であり、すべて特徴検出の基本的な理論と手法です。

OpencvでのAPIの紹介:

void resize(src,dst,size,int interpolation)
//src:源图像;dst:目标图像,
//size目标图像大小,可以是指定的尺寸或者放大缩小的比例
//指定插值方式,一般有四种插值方式可供选择,默认为线性插值法

2.画像​​ピラミッド

    画像ピラミッドは、画像内の一種のマルチスケール表現であり、主に画像のセグメンテーションに使用されます。これは、画像を多重解像度で説明するための効果的でシンプルな概念構造です。画像ピラミッドは、もともとマシンビジョンと画像圧縮に使用されていました。画像のピラミッドは、同じ元の画像から派生した、徐々に解像度が低下したピラミッド形状に配置された一連の画像です。段階的にダウンサンプリングすることで取得し、一定の終了条件に達するまでサンプリングを停止しません。ピラミッドの下部は処理される画像の高解像度表現であり、上部は低解像度の近似値です。画像をレイヤーごとにピラミッドと比較します。レベルが高いほど、画像は小さくなり、解像度は低くなります。

2つの一般的なタイプの画像ピラミッド

  • ガウスピラミッド:ダウン/ダウンサンプリングに使用され、メイン画像のピラミッド

  • ラプラシアンピラミッド:ピラミッドの下層画像から上層の非サンプリング画像を再構成するために使用されます。デジタル画像処理では、予測残差です。画像を最大限に復元し、ガウスピラミッドで使用できます。


ここに画像の説明を挿入2つのサンプルグラフピラミッドの簡単な違い:ガウスピラミッドは画像をダウンサンプリングするために使用されます。ダウンサンプリングは実際にはピラミッドの下部からアップサンプリングされ、解像度が低下することに注意してください。これは、私たちが理解しているピラミッドの概念の反対です。 (注);およびラプラシアンピラミッドは、ピラミッドのアップサンプリングの下部にある画像から画像を再構成するために使用されます。

     ピラミッドのi番目のレイヤーからi + 1番目のレイヤーを生成するには(i +1番目のレイヤーはG_i + 1と言います)、最初にG_1をガウスカーネルで畳み込み、次にすべての偶数行と偶数列を削除する必要があります。新しく取得した画像の面積は、ソース画像の4分の1になります。上記のプロセスに従って入力画像G_0に対して操作を実行することにより、ピラミッド全体を生成できます。

    画像がピラミッドの上位レベルに移動すると、サイズと解像度が低下します。OpenCVでは、PryDownを使用して、ピラミッドの上位レベルの画像から次のレベルの画像を生成できます。また、PryUpを使用すると、既存の画像が各次元で2倍に拡大されます。

    画像ピラミッドのアップサンプリングとダウンサンプリングは、それぞれOpenCV関数pyrUpとpyrDownによって実装されます。要約すれば:

  • 画像のアップサンプリング:pyrUp関数
  • 画像をダウンサンプリングします:pyrDown関数

    ここでの下方および上方のサンプリングは、画像のサイズ(ピラミッドの方向の反対)に対するものです。上方は画像サイズを2倍にすることを意味し、下方は画像サイズを半分にすることを意味します。そして、上の図に示されているピラミッドの方向を理解すると、ピラミッドの上向きの画像は実際には縮小していますが、これは逆です。

    ただし、PryUpとPryDownは逆数ではないことに注意してください。つまり、PryUpはダウンサンプリングの逆演算ではありません。この場合、画像は最初に各次元で元のサイズの2倍に拡大され、新しい行(偶数行)は0で埋められます。次に、指定されたフィルター(実際には各次元で2倍になっているフィルター)を畳み込み、「欠落している」ピクセルのおおよその値を推定します。PryDown()は、情報を失う関数です。元の高解像度画像を復元するには、ダウンサンプリング操作によって失われた情報を取得する必要があります。このデータは、ラプラシアンピラミッドに関連しています。

2.1ガウスピラミッド

    ガウスピラミッドは、ガウス平滑化とサブサンプリングによって一連のダウンサンプリングされた画像を取得します。つまり、K番目のガウスピラミッドは、平滑化とサブサンプリングによってK +1レベルのガウス画像を取得できます。ガウスピラミッドには次のものが含まれます。一連のローパスフィルター。カットオフ周波数は、上層から次の層に向かって2倍ずつ徐々に増加するため、ガウスピラミッドは広い周波数範囲にまたがることができます。ピラミッドのイメージは次のとおりです
ここに画像の説明を挿入
。さらに、各レイヤーには下から上に番号が付けられ、レベルはG_i + 1です(G_i + 1はi番目のレイヤーG_iよりも小さいことを示しています)。

  • 画像のダウンサンプリング操作は、画像を縮小することです。
    レベルG_i + 1のピラミッド画像を取得するための方法の手順は、次のとおりです。
    <1>画像G_iでガウスカーネル畳み込みを実行してガウスぼかしを実行します。
    <2>偶数の行と列をすべて削除します。

    得られた画像はG_i + 1の画像です。明らかに、結果の画像は元の画像の4分の1にすぎません。入力画像G_i(元の画像)で上記の手順を継続的に繰り返すことにより、ピラミッド全体が取得されます。同時に、ダウンサンプリングによって画像の情報が徐々に失われることもわかります。上記は画像のダウンサンプリングです。つまり、画像が縮小されます。

  • 画像のアップサンプリング
  • メソッドの手順は次のとおりです。
    <1>画像を各方向に2回展開し、新しい行と列に0を入力します。
    <2>同じカーネル(4を掛けたもの)を使用して、拡大した画像を畳み込みます。概算を取得します。 「新しいピクセル」の値

    得られた画像は拡大画像ですが、ズーム処理中に一部の情報が失われるため、元の画像に比べてぼやけます。ズームアウトおよびズームインの全プロセスでの情報の損失を減らしたい場合は、これらのデータはラプラスのピラミッドを形成しました。

要件:ラプラスピラミッドの場合、画像サイズは2のn乗* 2のn乗である必要があります。そうでない場合、エラーが報告されます
。dst= cv2.pyrDown(src)
dst:サンプリング結果
src:元の画像

import cv2 as cv
import numpy as np

#高斯金字塔
def pyramid_demo(image):
    level = 3#金字塔的层数
    temp = image.copy()#拷贝图像
    pyramid_images = []
    for i in range(level):
        dst = cv.pyrDown(temp)
        pyramid_images.append(dst)
        cv.imshow("pyramid_down_"+str(i), dst)
        temp = dst.copy()
    return pyramid_images


src = cv.imread("lena.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
c=pyramid_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

スクリーンショットは次のとおりです。
ここに画像の説明を挿入    ガウスフィルターはローパスフィルターと見なすことができ、各ガウスフィルターの後、特定の周波数値より下の周波数部分のみを画像に保持できるため、ガウスピラミッドもローパスピラミッド(それぞれ特定の周波数未満のコンポーネントのみが最初のレベルに保持されます)。

2.2ラプラシアンピラミッド

    ガウスピラミッドの計算を実行すると、ガウスフィルタリングとダウンサンプリングが継続されるため、多くの高周波信号が失われました。ラプラシアンピラミッドの目的は、これらの高周波信号を保存することです。これらの高周波信号を保存する方法は、[保存]です。違いの画像。たとえば、ラプラシアンピラミッドの0番目のレイヤーは、元の画像と、ダウンサンプリング(Reduce)してからアップサンプリング(Expand)した画像との差です。

    もう1つのポイントは、画像ピラミッドの重要なアプリケーションは、画像のセグメンテーションを実現することです。画像セグメンテーションの場合、最初に画像ピラミッドを確立する必要があります。次に、G_iとG_i + 1のピクセルが対応する関係の直後に続き、「親子」関係を確立します。高速初期セグメンテーションは、高レベルのピラミッドの低解像度画像で実行でき、その後、セグメンテーションをレイヤーごとに最適化できます。

    注:アップサンプリングとダウンサンプリングは非線形処理であり、不可逆的で損失の多い処理です。
結果=元の画像-最初に下から上へ
下:サイズが小さくなる
上:サイズが大きくなる

#图像金字塔
#高斯金字塔:reduce=2倍的高斯模糊+降采样(必须是一级一级来,不可越级);
#拉普拉斯金字塔:expand=扩大+卷积(升采样)
'''
图像金字塔方法的原理是:将参加融合的的每幅图像分解为多尺度的金字塔图像序列,将低分辨率的图像在上层,
高分辨率的图像在下层,上层图像的大小为前一层图像大小的1/4。层数为0,1,2……N。将所有图像的金字塔在
相应层上以一定的规则融合,就可得到合成金字塔,再将该合成金字塔按照金字塔生成的逆过程进行重构,得到融合金字塔。
'''
import cv2 as cv
import numpy as np
'''
拉普拉斯字塔:首先将原图像作为最底层图像G0(高斯金字塔的第0层),利用高斯核(5*5)对其进行卷积,
然后对卷积后的图像进行下采样(去除偶数行和列)得到上一层图像G1,将此图像作为输入,
重复卷积和下采样操作得到更上一层图像,反复迭代多次,形成一个金字塔形的图像数据结构
'''
def pyramid_demo(image):#高斯金字塔
    level = 3
    temp = image.copy()#复制一张
    pyramid_images = []
    for i in range(level):
        dst = cv.pyrDown(temp)#降     API,原理在上方
        pyramid_images.append(dst)#加入列表
        #cv.imshow("pyramid_down_"+str(i), dst)
        temp = dst.copy()#为temp赋新值
    return pyramid_images
def lapalian_demo(image)::#拉普拉斯金字塔
    pyramid_images = pyramid_demo(image)#首先得到高斯金字塔结果
    level = len(pyramid_images)
    for i in range(level-1, -1, -1):#从小图到大图
        if (i-1) < 0 :#最后一层特殊处理
            expand = cv.pyrUp(pyramid_images[i], dstsize=image.shape[:2])#内插放大后图像
            lpls = cv.subtract(image, expand)#它的每一层L0图像是高斯金字塔本层G0图像与其高一层图像G1经内插放大后图像*G1的差
            cv.imshow("lapalian_down_" + str(i), lpls)
        else:
            expand = cv.pyrUp(pyramid_images[i], dstsize=pyramid_images[i-1].shape[:2])
            lpls = cv.subtract(pyramid_images[i-1], expand)
            cv.imshow("lapalian_down_"+str(i), lpls)


#注意:图像的大小最好是2的n次方的倍数,否则结果会出问题,可以用resize调节大小
src = cv.imread("lena.png")#图必须要是2的N次倍数
#src=cv.resize(src,(512,512))
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
lapalian_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

スクリーンショットを実行する:
ここに画像の説明を挿入画像サイズは2の倍数である必要があることに注意してください。そうでない場合、エラーが報告されます

3、画像勾配

ソーベル演算子理論
図に示されているように、図の赤い点線の領域は髪の毛から皮膚までです。最初に髪の毛の領域を開くと、髪は黒く、ピクセルはポイントし、次に皮膚、ピクセルは比較的高く、次の図2が得られます。図2の一次導関数は、図3を取得するために取得され、最高の導関数は端にあります。
一次導関数は違いを生むことを意味します。
ここに画像の説明を挿入
ここに画像の説明を挿入演算子の合計は0です

ラプラシアン演算子理論、演算子の
ここに画像の説明を挿入ここに画像の説明を挿入
合計は0です

import cv2 as cv
import numpy as np

def sobel_demo(image):
    grad_x = cv.Sobel(image, cv.CV_32F, 1, 0) #x和y方向的结果
    grad_y = cv.Sobel(image, cv.CV_32F, 0, 1)
    #Scharr算子是Sobel算子的增强版,轮廓更加明显
    # grad_x = cv.Scharr(image, cv.CV_32F, 1, 0)  # x和y方向的结果
    # grad_y = cv.Scharr(image, cv.CV_32F, 0, 1)
    gradx = cv.convertScaleAbs(grad_x)#上一步的计算结果有正有负,把他们全部转化为绝对值
    grady = cv.convertScaleAbs(grad_y)#最后全部转换到6位的结果上去
    cv.imshow("gradient_x", grad_x)
    cv.imshow("gradient_y", grad_y)

    gradxy = cv.addWeighted(gradx, 0.5, grady, 0.5, 0)
    cv.imshow("gradient", gradxy)


src = cv.imread("C:/Users/lenovo/Desktop/opencv/daima/banknum/template-matching-ocr/images/lena.jpg")  #读取图片位置
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
sobel_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

実行中のスクリーンショット:
ここに画像の説明を挿入scharr演算子は、sobel演算子の拡張バージョンです。言うまでもなく、Sobelによって取得されたエッジがあまり良くない場合は、シャー演算子を検討してください。

import cv2 as cv
import numpy as np

def sobel_demo(image):
   
    #Scharr算子是Sobel算子的增强版,轮廓更加明显
    grad_x = cv.Scharr(image, cv.CV_32F, 1, 0)  # x和y方向的结果
    grad_y = cv.Scharr(image, cv.CV_32F, 0, 1)
    gradx = cv.convertScaleAbs(grad_x)#上一步的计算结果有正有负,把他们全部转化为绝对值
    grady = cv.convertScaleAbs(grad_y)#最后全部转换到6位的结果上去
    cv.imshow("gradient_x", grad_x)
    cv.imshow("gradient_y", grad_y)

    gradxy = cv.addWeighted(gradx, 0.5, grady, 0.5, 0)
    cv.imshow("gradient", gradxy)


src = cv.imread("C:/Users/lenovo/Desktop/opencv/daima/banknum/template-matching-ocr/images/lena.jpg")  #读取图片位置
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
sobel_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

スクリーンショットの実行:
ここに画像の説明を挿入ラプラシアン演算子の実装

import cv2 as cv
import numpy as np

def laplacian_demo(image):
    # dst = cv.Laplacian(image, cv.CV_32F)
    # lpls = cv.convertScaleAbs(dst)

    #手动定义一个拉普拉斯算子
    #kernel = np.array([[0, 1, 0], [1, -4, 1], [0, 1, 0]])#laplacian默认用的4邻域算子,即中间的值是-4
    kernel = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]])#用8邻域是增强版的

    dst = cv.filter2D(image, cv.CV_32F, kernel=kernel)
    lpls = cv.convertScaleAbs(dst)
    cv.imshow("laplacian_demo", lpls)



print("--------- Python OpenCV Tutorial ---------")
src = cv.imread("daqiu.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
lapalian_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

ランは、スクリーンショット:
ラプラシアン機能を使用する場合:
ここに画像の説明を挿入使用のデフォルトの4近傍の演算
ここに画像の説明を挿入ラプラス使用ラプラスによって強化8近傍オペレーター
ここに画像の説明を挿入参考ブログ:使用様々なピラミッドの画像勾配演算子での
画像ピラミッド
画像

おすすめ

転載: blog.csdn.net/weixin_44145452/article/details/112761159