Opencv-C++ 注記 (10): opencv-image ピクセル計算

1. 確率

デジタル画像はあるサイズの行列として理解できます.行列の各要素のサイズは画像内の各ピクセルの明暗を表します.したがって,統計行列の最大値はピクセルを見つけることです平均を計算すると、画像ピクセルの平均グレー レベルが計算され、画像全体の明るさと暗さを表すために使用できます。したがって、マトリックス データの統計処理も、画像ピクセルにおいて一定の重要性と役割を持ちます。OpenCV 4には画像ピクセルの最大値、最小値、平均値、平均二乗誤差など多くの統計を計算する機能が統合されており、次にこれらの機能に関連する機能について詳しく紹介します。

2.画像​​ピクセルの最大値と最小値を見つける

void cv::minMaxLoc(InputArray src,
                   double * minVal,
                   double * maxVal = 0,
                   Point * minLoc = 0,
                   Point * maxLoc = 0,
                   InputArray mask = noArray())

src: 最大値と最小値を見つける必要がある画像または行列。単一チャネル行列である必要があります。
minVal: 画像または行列の最小値。
maxVal: 画像または行列の最大値。
minLoc: 画像または行列内の行列の最小値の座標。
maxLoc: 画像または行列内の行列の最大値の座標。
マスク: 最大値を見つけるために画像または行列内の指定された領域を設定するために使用されるマスク。

ここでは、画像のピクセル座標を表すために使用される新しいデータ型 Point が表示されます。画像のピクセル座標軸は左上隅を座標原点とするため、水平方向が x 軸となり、垂直方向が x 軸になります。方向は y 軸であるため、Point (x,y) は、Point(columns, rows) として表されるイメージの行と列に対応します。OpenCVでは、2次元座標と3次元座標について様々なデータ型が設定されており、2次元座標のデータ型としては、整数座標cv::Point2i(またはcv::Point)、double型座標cv::Point2d、浮動小数点型が挙げられます。座標 cv::Point2f も、前述の 3D 座標の座標データ型を定義しており、数値「2」を「3」に変更するだけです。座標の x、y、z 軸の特定のデータについては、変数の x、y、z 属性を通じてアクセスできます。たとえば、Point.x は座標の x 軸データを読み取ることができます。 。

この関数によって実現される機能は、画像内の特定の領域の最大値を見つけることです。関数の最初のパラメータは、単一チャネルの行列を入力することです。この変数は単一チャネルの行列データである必要があることに注意してくださいマルチチャネル行列データの場合は、 cv::Mat::reshape() を使用して複数のチャネルを 1 つのチャネルに変更するか、各チャネルの最大値を個別に見つけて、比較してグローバル値を見つける必要があります。最大値。cv::Mat::reshape() の使用法については、コード リスト 3-8 に示されています。2 番目から 5 番目のパラメータは、それぞれ最小値、最大値、最小値位置、最大値位置へのポインタです。特定のパラメータを見つける必要がない場合は、このパラメータを NULL に設定できます。関数の最後のパラメータは、マスク行列は、上記の 4 つの値を検索する範囲をマークするために使用されます。パラメータのデフォルト値は noArray() であり、検索範囲が行列内のすべてのデータであることを意味します。

Mat cv::Mat::reshape(int  cn,int  rows = 0)

cn: 変換された行列のチャネル数。
rows: 変換後の行列の行数。パラメーターがゼロの場合、変換後の行数は変換前と同じです。

なお、
行列に最大値または最小値が複数ある場合、minMaxLoc()関数が最大値を出力する位置は、行を左から右に走査して初めて最大値が検出された位置となります。同時にパラメータを入力するときは、必ず値のアドレス文字を追加してください。
読者が minMaxLoc() 関数の原理と使用法をよりよく理解できるように、行列の最大値を見つけるためのサンプル プログラムをコード リスト 3-9 に示し、プログラム演算の最終結果を示します。図 3-6 と図 3-7 は、Image
Watch で表示される、作成された 2 つの行列とチャネル変換された行列の内容を示しています。

#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;
    float a[12]={
    
    1,2,3,4,5,10,6,7,8,9,10,0};
    Mat img=Mat(3,4,CV_32FC1,a);//单通道矩阵
    Mat imgs=Mat(2,3,CV_32FC2,a);//多通道矩阵
    double minVal,maxVal;//用于存放矩阵中的最大值和最小值
    Point minIdx,maxIdx;//用于存放矩阵中的最大值和最小值的位置

    /*寻找单通道矩阵中的最值*/
    minMaxLoc(img,&maxVal,&minVal,&minIdx,&maxIdx);
    cout << "img中最大值是:" << maxVal << " " << "在矩阵中的位置:" << maxIdx << endl;
    cout << "img中最小值是:" << minVal << " " << "在矩阵中的位置:" << minIdx << endl;

    /*寻找多通道矩阵中的最值*/
    Mat imgs_re=imgs.reshape(1,4);//将多通道矩阵变成单通道矩阵
    minMaxLoc(imgs_re,&minVal,&maxVal,&minIdx,&maxIdx);
    cout << "img中最大值是:" << maxVal << " " << "在矩阵中的位置:" << maxIdx << endl;
    cout << "img中最小值是:" << minVal << " " << "在矩阵中的位置:" << minIdx << endl;
    return 0;
}

ここに画像の説明を挿入
ここに画像の説明を挿入

3. 画像の平均と標準偏差を計算します。

画像の平均値は画像全体の明暗を示しており、画像の平均値が大きいほど画像全体が明るくなる。標準偏差は画像の明暗の変化のコントラストの度合いを表し、標準偏差が大きいほど画像の明暗の変化が顕著になります。OpenCV
4 では、画像の平均値を計算するmean()関数と、画像の平均値と標準偏差を同時に計算するmeanStdDev()関数が提供されています。次に、この2つの機能の詳しい使い方を紹介します。

cv::Scalar cv::mean(InputArray src,InputArray mask = noArray())

src: 平均化される画像行列。
マスク: 平均化される領域をマークするために使用されるマスク。

この関数は、画像行列の各チャネルの平均値を計算するために使用されます。関数の最初のパラメータは、平均化する画像行列を入力するために使用されます。チャネル数は 1 ~ 4 です。この関数の戻り値は cv::Scalar 型の変数であることに注意してください。関数の戻り値は 4 ビットで、それぞれ入力画像の 4 チャネルの平均値を表します。チャネルが 1 つしかない場合、戻り値は最後の 3 ビットがすべて 0 になります。たとえば、単一チャネルの平均値が 1 の画像をこの関数に入力すると、出力結果は [1,0,0,0] になります。 ] を使用すると、cv::Scalar[n] の平均を通じて n 番目のチャネルを表示できます。この関数の第 2 パラメータは、画像の平均値を計算する範囲を制御するために使用されます。第 1 パラメータでは、第 2 パラメータの画素値が 0 の画素が削除されます。計算原理は式 (3.5) に示されています。 ). 未入力時 第2パラメータを使用した場合は、第1パラメータの全ピクセルの平均値を計算することになります。
ここに画像の説明を挿入
このうち、c 番目のチャンネルの平均値を表し、c 番目のチャンネルのピクセルの階調値を表します。
meansStdDev() 関数は、画像の各チャネルの平均値と標準偏差を同時に計算できます。その関数プロトタイプをコード リスト 3-11 に示します。

void cv::meanStdDev(InputArray src,OutputArray mean,OutputArray stddev,InputArray mask = noArray())
src:待求平均值的图像矩阵。
mean:图像每个通道的平均值,参数为Mat类型变量。
stddev:图像每个通道的标准方差,参数为Mat类型变量。
mask:掩模,用于标记求取哪些区域的平均值和标准方差。

この関数の最初のパラメータは、前のmean()関数の最初のパラメータと同じで、1~4チャンネルの画像を指定できます。違いは、この関数には戻り値がなく、平均値と標準偏差が含まれていることです。 1番目の関数で画像を出力します。2番目と3番目のパラメータはmean()関数とは異なり、平均値と標準偏差を格納するMat型変数を使用します。変数内のデータ数は同じです。最初のパラメータのチャネル数入力画像にチャネルが 1 つしかない場合、この関数で計算される平均値と標準偏差変数にはデータが 1 つだけ存在します。この関数の計算原理を式(3.6)に示します。

ここに画像の説明を挿入

#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;
    float a[12]={
    
    1,2,3,4,5,10,6,7,8,9,10,0};
    Mat img=Mat(3,4,CV_32FC1,a);//单通道矩阵
    Mat imgs=Mat(2,3,CV_32FC2,a);//多通道矩阵

    cout << "/* 用meanStdDev同时求取图像的均值和标准方差 */" << endl;
    Scalar myMean;
    myMean=mean(imgs);
    cout<<"imgs均值 = "<<myMean<<endl;
    cout<<"imgs第一个通道的均值 = "<<myMean[0]<<" "
        <<"imgs第二个通道的均值 = "<<myMean[1]<<endl;

    cout << "/* 用meanStdDev同时求取图像的均值和标准方差 */" << endl;
    Mat myMeanMat,myStddevMat;

    meanStdDev(img,myMeanMat,myStddevMat);
    cout << "img均值=" << myMeanMat << " " << endl;
    cout << "img标准方差=" << myStddevMat << endl << endl;
    meanStdDev(imgs,myMeanMat,myStddevMat);
    cout << "img均值=" << myMeanMat << " " << endl;
    cout << "img标准方差=" << myStddevMat << endl << endl;
    return 0;
}

ここに画像の説明を挿入

4. 2枚の画像の比較演算

OpenCV 4 は、2 つのイメージ内の各ピクセルの大きいまたは小さいグレー値を計算する max() 関数と min() 関数を提供します。これら 2 つの関数は、2 つのイメージ内の各要素のグレー値をそれぞれ比較します。グレースケール値

 void cv::max(InputArray src1,InputArray src2,OutputArray dst) void
 cv::min(InputArray src1,InputArray src2,OutputArray dst)
  • src1: 最初の画像行列。任意の数のチャネルを持つ行列にすることができます。
  • src2: 2 番目のイメージ行列、サイズ、チャネル数、データ型は src1 と一致する必要があります。
  • dst: 対応する位置の大きい方(小さい方)のグレー値を保持した後の画像行列、サイズ、チャネル数、データ型はsrc1と一致します。

この関数の機能は比較的単純で、画像の各ピクセルのサイズを比較し、必要に応じて大きいか小さい値を保持し、最後に新しい画像を生成します。たとえば、最初の画像のピクセル値が 100、2 番目の画像のピクセル値が 10 の場合、出力画像のピクセル値は 100 になります。これら 2 つの関数のコード実装プロセスと演算結果をコード リスト 3-14 に示し、演算結果を図 3-9、図 3-10、図 3-11 に示します。この比較演算は主にマトリックス型データの処理に使用され、マスク画像との比較演算によりマット化やチャネル選択の効果を得ることができます。

#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;
    float a[12]={
    
    1,2,3.3,4,5,9,5,7,8.2,9,10,2};
    float b[12]={
    
    1,2.2,3,1,3,10,6,7,8,9.3,10,1};
    Mat imga=Mat(3,4,CV_32FC1,a);
    Mat imgb=Mat(3,4,CV_32FC1,b);
    Mat imgas=Mat(2,3,CV_32FC2,a);
    Mat imgbs=Mat(2,3,CV_32FC2,b);

    //对两个单通道矩阵进行比较远算
    Mat myMax,myMin;
    max(imga,imgb,myMax);
    min(imga,imgb,myMin);

    //对两个多通道矩阵进行比较运算
    Mat myMaxs,myMins;
    max(imgas,imgbs,myMaxs);
    min(imgas,imgbs,myMins);

    //对两张彩色图像进行比较运算
    Mat img0=imread("lena.png");
    Mat img1=imread("noobcv.jpg");
    if(img0.empty()||img1.empty()){
    
    
        cout<<"请确认图像文件名称是否正确"<<endl;
        return -1;
    }
    Mat comMin,comMax;
    max(img0,img1,comMax);
    min(img0,img1,comMin);
    imshow("comMin",comMin);
    imshow("comMax",comMax);

    //与掩模进行比较运算
    Mat src1=Mat::zeros(Size(512,512),CV_8UC3);
    Rect rect(100,100,300,300);
    src1(rect)=Scalar(255,255,255);//生成一个300*300的掩模
    Mat comsrc1,comsrc2;
    min(img0,src1,comsrc1);
    imshow("comsrc1",comsrc1);

    Mat src2=Mat(512,512,CV_8UC3,Scalar(0,0,255));//生成一个显示红色的低通掩模
    min(img0,src2,comsrc2);
    imshow("comsrc2",comsrc2);

    //对两张图片灰度图像进行比较运算
    Mat img0G,img1G,comMinG,comMaxG;
    cvtColor(img0,img0G,COLOR_BGR2GRAY);
    cvtColor(img1,img1G,COLOR_BGR2GRAY);
    max(img0G,img1G,comMaxG);
    max(img0G,img1G,comMaxG);
    imshow("comMinG",comMinG);
    imshow("comMaxG",comMaxG);
    return 0;
}

ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入

5. 2枚の画像の論理演算

OpenCV 4 は、2 つの画像ピクセル間の AND、OR、XOR、NOT 演算のための 4 つの関数 **bitwise_and()、bitwise_or()、bitwise_xor() および bitwise_not()** をコード リスト 3-15 で提供します。 これら 4 つの関数プロトタイプ関数は に与えられます。関数の使用法を理解する前に、画像ピクセルの論理演算のルールを理解しましょう。画像ピクセル間の論理演算は数値間の論理演算と同じであり、具体的な規則は図 3-12 に示されています。ピクセルの否定演算は 1 つの値に対してのみ実行できるため、図 3-12 でピクセルを否定する場合、否定演算は画像 1 のピクセル値に対して実行されます。ピクセル値が0と1のみの場合、図の最初の4行のデータはすべての演算ルールに対応しますが、CV_8Uタイプの画像ピクセル値は0から255であり、このときの論理演算はピクセル値を 2 進数に変換します。CV_8U 型は 8 ビット データなので、0 を否定すると 11111111、つまり 255 になります。図 3-12 のデータの最後の行では、ピクセル値 5 に対応するバイナリ値は 101、ピクセル値 6 に対応するバイナリ値は 110 であるため、AND 演算は 100 (4)、つまり演算は 111 になります。 (7)、XOR 演算は 011 (3)、ピクセル値 5 を否定して 11111010 (250) を取得します。ピクセルの配列演算の原理を理解したところで、
OpenCV 4で提供されている配列演算関数の使い方を見てみましょう。
ここに画像の説明を挿入

//像素求与运算
  void cv::bitwise_and(InputArray src1,
                           InputArray src2,
                           OutputArray dst,
                          InputArray mask = noArray()
                            )
  //像素求或运算
   void cv::bitwise_or(InputArray src1,
                     InputArray src2,
                      OutputArray dst,
                      InputArray mask = noArray()
                        )
   //像素求异或运算
   void cv::bitwise_xor(InputArray src1,
                       InputArray src2,
                       OutputArray dst,
                       InputArray mask = noArray()
                        )
   //像素求非运算
   void cv::bitwise_not(InputArray src,
                       OutputArray dst,
                       InputArray mask = noArray()
                         )
  • src1: 最初の画像行列。マルチチャネル画像データにすることができます。
  • src2: 2 番目のイメージ行列、サイズ、チャネル数、データ型は src1 と一致する必要があります。
  • dst: 論理演算の出力結果、サイズ、チャネル数、データ型はsrc1と一致します。
  • マスク: イメージまたは行列の論理演算の範囲を設定するために使用されるマスク。

これらの関数はすべて、対応する論理演算を実行します。論理演算を実行するときは、2 つの画像行列間のサイズ、データ型、チャネル数が同じであることを確認する必要があります。複数のチャネルが論理演算を実行する場合、異なるチャネルは独立して実行されます。の。2 つの画像ピクセル間の論理演算をより直感的に理解するために、2 つの白黒画像ピクセルの論理演算のサンプル プログラムをコード リスト 3-16 に示します。

#include <opencv2\opencv.hpp>
   2.  #include <iostream>
   3.  #include <vector>
   4.  
   5.  using namespace std;
   6.  using namespace cv;
   7.  
   8.  int main()
   9. {
    
    
   10.    Mat img = imread("lena.png");
   11.    if (img.empty())
   12.    {
    
    
   13.      cout << "请确认图像文件名称是否正确" << endl;
   14.      return -1;
   15.    }
   16.    //创建两个黑白图像
   17.    Mat img0 = Mat::zeros(200, 200, CV_8UC1);
   18.    Mat img1 = Mat::zeros(200, 200, CV_8UC1);
   19.    Rect rect0(50, 50, 100, 100);
   20.    img0(rect0) = Scalar(255);
   21.    Rect rect1(100, 100, 100, 100);
   22.    img1(rect1) = Scalar(255);
   23.    imshow("img0", img0);
   24.    imshow("img1", img1);
   25.  
   26.    //进行逻辑运算
   27.    Mat myAnd, myOr, myXor, myNot, imgNot;
   28.    bitwise_not(img0, myNot);
   29.    bitwise_and(img0, img1, myAnd);
   30.    bitwise_or(img0, img1, myOr);
   31.    bitwise_xor(img0, img1, myXor);
   32.    bitwise_not(img, imgNot);
   33.    imshow("myAnd", myAnd);
   34.    imshow("myOr", myOr);
   35.    imshow("myXor", myXor);
   36.    imshow("myNot", myNot);
   37.    imshow("img", img);
   38.    imshow("imgNot", imgNot);
   39.    waitKey(0);
   40.    return 0;
   41.  }

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/jiyanghao19/article/details/131251381