記事ディレクトリ
I. 概要
プログラムの前のセクションで白と黒のみの画像を生成しましたが、この「黒または白」画像ピクセルのグレー値は、データ型に関係なく、最大値と最小値の 2 つの値のみを持ちます。 . したがって、それはバイナリ画像と呼ばれます。高度に圧縮して保存スペースを節約できるバイナリ画像にはいくつかの種類がありますが、非バイナリ画像を計算によってバイナリ画像に変換するプロセスは画像の二値化と呼ばれます。OpenCV4 では画像 2 値化を実装するために、threshold() とadaptiveThreshold() という 2 つの関数が提供されています。最初に、threshold() 関数の使用法を紹介します。この関数の関数プロトタイプは、コード リスト 3-17 に示されています。
double cv::threshold(InputArray src,OutputArray dst,double thresh,double maxval,int type)
- src: 2 値化する画像。画像には CV_8U と CV_32F の 2 つのデータ型のみを使用できます。画像チャンネル数の要件は、選択した二値化方法に関連します。
- dst: 入力画像と同じサイズ、データ型、チャネル数を持つ 2 値化画像。
- thresh: 2値化の閾値。
- maxval: 2値化処理の最大値 この関数はTHRESH_BINARYとTHRESH_BINARY_INVの2つの2値化方式でのみ使用されますが、他の方式を使用する場合にも入力が必要です。
- type: 画像の二値化方法を選択するフラグ。
この関数は、多くの 2 値化手法を統合したものであり、そのすべてが関数を実装しています。つまり、しきい値が与えられ、すべてのピクセルのグレー値としきい値の関係を計算し、最終的な比較結果を取得します。関数内の一部のしきい値比較メソッドの出力結果のグレー値はバイナリではなく、値の範囲がありますが、最も一般的に使用される関数を反映するために、引き続きそれをバイナリ化関数またはしきい値比較関数と呼びます。関数の一部のパラメータと戻り値は特定のアルゴリズムでのみ役立ちますが、これらのアルゴリズムが使用されない場合でも、関数を使用するときに明示的に指定する必要があり、デフォルトにすることはできません。関数の最後のパラメータは 2 値化計算方法を選択するフラグです。2 値化方法を選択し、どのパラメータが関数の計算結果に影響を与えるかを制御できます。選択できるフラグの範囲と意味は表 3 に示されています-2.
次に、二値化の原理と各フラグに対応する必要なパラメータについて詳しく紹介します。
2 つ、THRESH_BINARY と THRESH_BINARY_INV
これら 2 つのフラグは逆の 2 値化方法です。THRESH_BINARY はグレースケール値としきい値 (3 番目のパラメーター thresh) を比較します。グレースケール値がしきい値より大きい場合は、グレースケール値を関数の 4 番目のパラメーター maxval の値に変更します。それ以外の場合は、グレースケール値を変更します。グレースケール値を 0 にします。THRESH_BINARY_INV フラグはこの処理の逆で、グレー値がしきい値より大きい場合はグレー値が 0 に変更され、そうでない場合はグレー値が maxval の値に変更されます。これら 2 つのフラグの計算式を式 (3.7) に示します。
3、THRESH_TRUNC
このフラグは、画像のグレー値の新しい最大値をリセットし、新しい最大値よりも大きいすべてのグレー値を新しい最大値にリセットすることに相当し、具体的なロジックはグレー値をしきい値と比較することです。 thresh 、グレー値が thresh より大きい場合は、グレー値を thresh に変更します。それ以外の場合は、グレー値を変更しません。このメソッドは関数の 4 番目のパラメーター maxval の値を使用しないため、maxval の値はこのメソッドには影響しません。この符号の計算式を式(3.8)に示します。
4 つ、THRESH_TOZERO と THRESH_TOZERO_INV
これら 2 つのフラグは、逆のしきい値比較方法です。THRESH_TOZERO は、グレー値としきい値 thresh を比較することを意味します。グレー値が thresh より大きい場合は変更されず、そうでない場合はグレー値が 0 に変更されます。THRESH_TOZERO_INV メソッドはその逆で、グレー値をしきい値 thresh と比較し、グレー値が thresh 以下の場合は変更されず、そうでない場合はグレー値が 0 に変更されます。これら 2 つのメソッドはどちらも関数の 4 番目のパラメーター maxval の値を使用しないため、maxval の値はこのメソッドには影響しません。これら 2 つのフラグの計算式を式 (3.9) に示します。
最初の 5 つのフラグはすべてマルチチャンネル画像の入力をサポートしており、計算中に各チャンネルのしきい値比較が実行されます。上記の閾値比較方法をより直観的に理解するために、画像の濃淡値が連続的に変化する信号であると仮定し、閾値比較方法をフィルタと比較し、連続信号がフィルタを通過した後の信号の形状を描画します。結果は図 3-14 に示されており、図中の赤い線は設定されたしきい値、黒い線は元の信号がフィルターを通過した後の信号形状です。
5. THRESH_OTSU と THRESH_TRIANGLE
これら 2 つのフラグは、しきい値の比較方法ではなく、しきい値を取得する方法であり、「THRESH_BINARY|THRESH_OTSU」など、前の 5 つのフラグと併用できます。最初の 5 つのフラグは、関数を呼び出すときにしきい値を手動で設定する必要があります。画像を知らない場合に無理なしきい値を設定すると、処理された効果に深刻な影響を及ぼします。) およびトライアングル メソッド (TRIANGLE) ** 画像の濃淡値分布特性と組み合わせて二値化の閾値を求め、閾値は関数の戻り値の形式で与えられます。したがって、これら 2 つのフラグのいずれかが関数の最後のパラメーターに設定されている場合、関数の 3 番目のパラメーター thresh はシステムによって自動的に指定されますが、関数呼び出し時にデフォルトに設定することはできませんが、プログラムは使用しません。この値。
これまでのところ、OpenCV 4 はこれら 2 つのフラグに対してタイプ CV_8UC1 のイメージの入力のみをサポートしていることに注意してください。Threshold() 関数はグローバルに 1 つのしきい値のみを使用しますが、実際の状況では、照明ムラや影の存在により、グローバルに 1 つのしきい値だけでは、関数によって影の領域の白い部分も黒に 2 値化されます。 adaptiveThreshold() 関数 局所適応しきい値の 2 値化メソッドが提供されており、この関数の関数プロトタイプをコード リスト 3-18 に示します。
void cv::adaptiveThreshold(InputArray src,
OutputArray dst,
double maxValue,
int adaptiveMethod,
int thresholdType,
int blockSize,
double C
)
- src: バイナリ化される画像。画像は CV_8UC1 データ型のみにすることができます。
- dst: 入力画像と同じサイズとデータ型を持つ 2 値化画像。
- maxValue: 2値化の最大値。
- adaptiveMethod: 閾値を決定するための自作メソッド。平均法 ADAPTIVE_THRESH_MEAN_C とガウス法 ADAPTIVE_THRESH_GAUSSIAN_C の 2 種類に分かれます。
- ThresholdType: 画像の 2 値化方法を選択するためのフラグ。THRESH_BINARY と THRESH_BINARY_INV のみを指定できます。
- blockSize: しきい値の近傍ピクセルのサイズを適応的に決定します。通常は 3、5、または 7 の奇数です。C: 平均または加重平均から減算する定数。正または負の値を指定できます。
この関数は、グレースケール画像を 2 値画像に変換し、blockSize* blockSize 近傍のしきい値を平均法とガウス法により適応的に計算し、2 値化します。原理は前と同じです。ここでは詳細に立ち入りません。
画像の二値化の効果を直感的に体験するために、コードリスト 3-19 にカラー画像とグレースケール画像を二値化するサンプルプログラムを示します。
#include<iostream>
#include<vector>
#include<string>
#include <opencv2/opencv.hpp>
#include "opencv/highgui.h"
using namespace std;
using namespace cv;
int main(int argc,char** argv) {
cout<<"OpenCv Version: "<<CV_VERSION<<endl;
Mat img=imread("699342568.jpg");
if(img.empty()){
cout<<"请确认输入的图片的路径是否正确"<<endl;
return -1;
}
Mat gray;
cvtColor(img,gray,COLOR_BGR2GRAY);
Mat img_B,img_B_V,gray_B,gray_B_V,gray_T,gray_T_V,gray_TRUNC;
//彩色图像二值化
threshold(img,img_B,125,255,THRESH_BINARY);
threshold(img,img_B_V,125,255,THRESH_BINARY_INV);
imshow("img_B",img_B);
imshow("img_B_V",img_B_V);
//灰度图像二值化
threshold(gray,gray_B,125,255,THRESH_BINARY);
threshold(gray,gray_B_V,125,255,THRESH_BINARY_INV);
imshow("gray_B",gray_B);
imshow("gray_B_V",gray_B_V);
//灰度图像TOZERO变换
threshold(gray,gray_T,125,255,THRESH_TOZERO);
threshold(gray,gray_T_V,125,255,THRESH_TOZERO_INV);
imshow("gray_T",gray_T);
imshow("gray_T_V",gray_T_V);
//灰度图像TRUNC变换
threshold(gray,gray_TRUNC,125,255,THRESH_TRUNC);
imshow("gray_TRUNC",gray_TRUNC);
//灰度图像大津法和三角法二值化
Mat img_Thr=imread("threshold.jpg",IMREAD_GRAYSCALE);
Mat img_Thr_0,img_Thr_T;
threshold(img_Thr,img_Thr_0,100,255,THRESH_BINARY|THRESH_OTSU);
threshold(img_Thr,img_Thr_T,125,255,THRESH_BINARY|THRESH_TRIANGLE);
imshow("img_Thr",img_Thr);
imshow("img_Thr_0",img_Thr_0);
imshow("img_Thr_T",img_Thr_T);
//灰度图像自适应二值化
Mat adaptive_mean,adaptive_gauss;
adaptiveThreshold(img_Thr,adaptive_mean,255,ADAPTIVE_THRESH_MEAN_C,THRESH_BINARY,55,0);
adaptiveThreshold(img_Thr,adaptive_gauss,255,ADAPTIVE_THRESH_GAUSSIAN_C,THRESH_BINARY,55,0);
imshow("adaptive_mean",adaptive_mean);
imshow("adaptive_gauss",adaptive_gauss);
waitKey(0);
return 0;
}
6. LUTルックアップテーブル
閾値比較方式の閾値は 1 つだけですが、複数の閾値を比較する必要がある場合はルックアップ テーブル (Look-Up-Table、LUT) を使用する必要があります。簡単に言うと、LUT ルックアップ テーブルは、ピクセル グレー値のマッピング テーブルであり、ピクセル グレー値をインデックスとして使用し、グレー値マッピング後の値をテーブルの内容として使用します。たとえば、文字を格納するための長さ 5 の配列があります。LUT ルックアップ テーブルは、この配列を通じて 0 を a、1 から b などにマッピングします。マッピング関係は です。
LUT() 関数は、画像ピクセルのグレー値の LUT ルックアップ テーブル関数を実現するためにOpenCV 4 で提供されており、関数のプロトタイプはコード リスト 3-20 に示されています。
void cv::LUT(InputArray src,
InputArray lut,
OutputArray dst
)
-
src: 入力画像行列。そのデータ型は CV_8U のみです。
-
lut: 256 ピクセルのグレー値のルックアップ テーブル、単一チャネルまたは src と同じ数のチャネル。
-dst: src と同じサイズ、lut と同じデータ型の出力イメージ行列。
この関数の最初の入力パラメータで必要なデータ型は CV_8U 型である必要がありますが、マルチチャネル画像行列でも構いません。2 番目のパラメーターの説明によると、入力は 1×256 行列で、各ピクセルのグレー値がマッピングされた後の値が格納されることがわかります。その形式は図 3-17 に示されています。2 番目のパラメータが単一チャネルの場合、入力変数の各チャネルは LUT ルックアップ テーブルに従ってマッピングされ、2 番目のパラメータがマルチチャネルの場合、入力変数の i 番目のチャネルは 2 番目のパラメータに従ってマッピングされます。マッピング用の i 番目のチャネル LUT ルックアップ テーブル。前の関数とは異なり、関数の出力画像のデータ型は元の画像のデータ型と一致しませんが、LUT ルックアップ テーブルのデータ型と一致します。これは、元のグレー値がマッピングされているためです。新しい空間なので、新しい空間のデータ型と一致する必要があります。
画像処理後の LUT ルックアップ テーブルの効果を理解するために、LUT() 関数を使用してグレースケール画像とカラー画像を処理するサンプル プログラムをコード リスト 3-21 に示します。プログラムでは 3 チャンネルのルックアップ テーブルが使用されています。カラー画像をマッピングします。
#include<iostream>
#include<vector>
#include<string>
#include <opencv2/opencv.hpp>
#include "opencv/highgui.h"
using namespace std;
using namespace cv;
int main(int argc,char** argv) {
cout<<"OpenCv Version: "<<CV_VERSION<<endl;
//LUT查找表第一层
uchar lutFirst[256];
for(int i=0;i<256;++i){
if(i<=100)lutFirst[i]=0;
else if(i>100&&i<=200)lutFirst[i]=100;
else lutFirst[i]=255;
}
Mat lutOne(1,256,CV_8UC1,lutFirst);
//LUT查找表第二层
uchar lutSecond[256];
for(int i=0;i<256;++i){
if(i<=100)lutSecond[i]=0;
else if(i>100&&i<=150)lutSecond[i]=100;
else if(i>150&&i<=200)lutSecond[i]=150;
else lutSecond[i]=255;
}
Mat lutTwo(1,256,CV_8UC1,lutSecond);
//LUT查找表第三层
uchar lutThird[256];
for(int i=0;i<256;++i){
if(i<=100)lutThird[i]=0;
else if(i>100&&i<=200)lutThird[i]=100;
else lutThird[i]=255;
}
Mat lutThree(1,256,CV_8UC1,lutThird);
//拥有三通道的LUT查找表矩阵
vector<Mat>mergeMats;
mergeMats.push_back(lutOne);
mergeMats.push_back(lutTwo);
mergeMats.push_back(lutThree);
Mat LutTree;
merge(mergeMats,LutTree);
//计算图像的查找表
Mat img=imread("lena.jpeg");
if(img.empty()){
cout<<"请确认输入的图片路径是否正确"<<endl;
return -1;
}
Mat gray,out0,out1,out2;
cvtColor(img,gray,COLOR_BGR2GRAY);
LUT(gray,lutOne,out0);
LUT(img,lutOne,out1);
LUT(img,LutTree,out2);
imshow("out0",out0);
imshow("out1",out1);
imshow("out2",out2);
waitKey(0);
return 0;
}