山東大学デジタル画像処理実験 (2)

序文

  • 今回は「コントラストと明るさの調整」と「背景減算の2つの実験」
  • 送信元アドレスは文末に記載

コントラストと明るさの調整実験

実験中に遭遇し解決した問題

  • 質問 1

    • 問題:sigmoid関数ないが、どのようなsigmoid関数を使えばいいのかわからない
    • 解決策: インターネットを検索して、コントラストと明るさの一般的な調整式を見つけます。コントラストを調整する場合、それを掛けた係数がピクセル値の前に追加されます。明るさを調整するときは、変数を使用してピクセル値を加算または減算します
  • 質問 2:

    • 問題:sigmoid関数ますが、特定の値は考慮されず、関数値は [-5,5] 内でのみ大幅に変化します

    • 解決策: ピクセル変換式を調整する

      • 元の式は

        int t = source_image.at<Vec3b>(y, x)[c];
        transformed_image.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(t * ((contrast_value*0.1 / (1.00 + exp(-t))) + 1));
        
      • 調整式は

        double t = ((source_image.at<Vec3b>(y, x)[c] - 127) / 255.00) * contrast_value * 0.1;//[-10, 10]
        transformed_image.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(source_image.at<Vec3b>(y, x)[c] * ((1.00 / (1.00 + exp(-t))) + 0.3) + bright_value - 100);
        
      • -127結果を正負にして、小さなピクセルが1 + e − t 1+e^{-t}になるようにするためです。1+tが大きいほど、コントラスト調整後のピクセル値は小さくなります。逆に大きい画素値の調整は小さい画素値ほど急激ではないので、両者の画素差が大きくなってしまうので、コントラストを調整します。

      • /255ttを制限することですtの範囲。べき乗関数がより明確に変化する領域で可能な限り変化します。

      • contrast_valueコントラスト調整のためにスライダーを変更する必要がある値です

      • 1 1 + e − t + 0.3 \frac{1}{1+e^{-t}} + 0.31 +−t _1+0.3の場合、係数が追加されます。係数が追加されない場合、コントラストを調整するだけでは、変換されたピクセル値が常に元のピクセル値よりも小さくなるため、これは望ましくありません。もう1つの理由は、これによりtttの役割、 ttをさせないでくださいtは非常に大きな影響力を持っています。(付加価値の大きさは自分でコントロールできる)

      • bright_value単純に明るさ調整用のピクセル値を調整した方がわかりやすい

  • 問題点 3: 調整式を使用して元の画像を取得することは困難です。個人的には非線形変換を利用しているためだと思いますが、現時点では解決策がありません

結果分析と経験

調整効果はより明白で正常であり、実験結果は期待される効果を達成しています。

  • シグモイド関数を使って元の画像を取得するのは難しい

  • コントラストが一定の範囲を超えると、画像のリアルさが失われます
    ここに画像の説明を挿入

ここに画像の説明を挿入

バックグラウンド減算実験

実験中に遭遇し解決した問題

  • 質問 1

    • 問題: 2 つの画像の対応する位置ピクセルを差し引いて得られた画像の効果が非常に低い

ここに画像の説明を挿入
誤検出:

  • 画像のピクセル値が背景画像の対応する位置のピクセル値とあまり変わらない場合、区別が難しく、減算後、前景画像の位置は基本的に黒であり、期待される要件を満たしていません.

  • 上の写真を例にすると、人物の画素値が背景の画素値よりも小さい場合、人物の画素値から背景の画素値を引いた値がオーバーフローしないように処理され、人物の対応する位置の画素値が結果のイメージは 0 であり、期待される要件を満たしていません。

    • 解決策: より良い解決策を見つけ、メディアン フィルターを使用してノイズ ポイントを削除します。合計は、2 つの画像の各ピクセルの 3 つのチャネルの差の 2 乗を合計し、次に合計の 2 乗をとることによって得られます。しきい値を手動で設定します。合計がこのしきい値より大きい場合、ピクセルの 3 つのチャネルは 255 (白) に設定され、それ以外の場合は 0 (黒) に設定されます。その結果、最適なしきい値は 75 ~ 100 であり、最終的に選択されたしきい値は 90 であることがわかりました。

結果分析と経験

文字の前景は基本的に抽出されているが、まだノイズが残っていることがわかる

  • バックグラウンド減算実験では、減算の基準を決定するのは簡単ではないため、いくつかのノイズ削減アルゴリズムを調べることができます

  • バックグラウンド減算実験の閾値を90とした時の結果です。望ましい効果を達成するための明確な輪郭

ここに画像の説明を挿入

遭遇したナレッジポイント

関数で

  • シングル チャネル イメージ "picture1" の場合、picture1.at(i,j) は、行 i および列 j のピクセル値を表します。

  • RGB 画像 "picture2" などのマルチチャンネル画像の場合、picture2.at(i,j)[c] を使用して、特定のチャンネルの (i,j) 位置のピクセル値を表すことができます。

共通型 Vec3b

Vec3b は vector<uchar, 3> と見なすことができます。つまり、長さ 3 の uchar 型のベクトル vector です。

由于在OpenCV中,使用imread读取到的Mat图像数据,都是用uchar类型的数据存储,对于RGB三通道的图像,每个点的数据都是一个Vec3b类型的数据。使用at定位方法如下:
 
img.at<Vec3b>(row, col)[0] = 255;  // 这是指修改B通道数据
img.at<Vec3b>(row, col)[1] = 255;  // 这是指修改G通道数据
img.at<Vec3b>(row, col)[2] = 255;  // 这是指修改R通道数据

srcImage.at<uchar>(j, i) //表示的是  j 行 i 列 的这个像素
srcImage.at<uchar>(Point(j, i)) //表示的是 坐标(j,i)的像素

saturate_cast

  • saturate_cast は、主にカラー オーバーフロー操作を防止するためのものです。
  • 画像処理上、足し算、引き算、掛け算、割り算のいずれであっても、ピクセルのグレー値(0~255)の範囲を超えてしまいますが、saturate_cast関数の機能は、演算後の結果がマイナスの場合、 0 に変換し、結果が 255 を超える場合は 255 になります。

Mat::ゼロ

  • 各ピクセルのチャネルごとに 0 のマップを作成します
Mat m = Mat::zeros(2, 2, CV_8UC3);//直接指明size和类型

transformed_image = Mat::zeros(source_image.size(), source_image.type());//创建一个和source_image一样类型的图

createTrackbar

スライダーを作成する

  • コールバック関数は createTrackbar で使用されます
CV_EXPORTS int createTrackbar(const String& trackbarname,
                              const String& winname,
                              int* value, 
                              int count,                                        
                              TrackbarCallback onChange = 0,
                              void* userdata = 0);    
  • スライダー名
  • スライダーが配置されているウィンドウの名前
  • スライダーの初期値を設定し、後でスライダーの位置を記録するために使用します (ユーザーがスライダーの位置を変更するため、値が変化します)
  • トラックの最大値、スライダーがスライドできる範囲は [0, count]
  • 折り返し電話
  • デフォルトは 0 で、ユーザーがコールバック関数に渡すデータです。3 番目の値がグローバル変数の場合、この値は無視されます
namedWindow("Transformed Window", WINDOW_AUTOSIZE);
createTrackbar("contrast", "Transformed Window", &contrast_value, 200, ContrastAndBright , 0);
createTrackbar("bright", "Transformed Window", &bright_value, 200, ContrastAndBright , 0);

static void ContrastAndBright(int pos , void* userdata) {
    //value传值给pos , createTrackbar的第六个参数传递给userdata
    for (int y = 0; y < source_image.rows; y++)
        for (int x = 0; x < source_image.cols; x++)
            for (int c = 0; c < 3; c++){
                double t = ((source_image.at<Vec3b>(y, x)[c] - 127) / 225.00) * contrast_value * 0.1;
                transformed_image.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(source_image.at<Vec3b>(y, x)[c] * ((1.00 / (1.00 + exp(-t))) + 0.3) + bright_value - 100);
            }
    imshow("Display Window", source_image);
    imshow("Transformed Window", transformed_image);
}

ソース アドレス: Computer-Vision/Experiment 1/メイン SDU-NSY/Computer-Vision のソース コード (github.com)

おすすめ

転載: blog.csdn.net/qq_52852138/article/details/127038134