Opencv-C++ 注 (4): opencv での MAT イメージへのアクセス

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

1. ピクセルアクセス

アクセス方法にて

以减少图像中颜色数量为例子。假设图像为256种颜色,将它变成64中颜色,
只需要将原来的颜色除以div = 4以后再乘以div = 4,最后加上div / 2就可以实现该操作。

at メソッド: cv::Mat の at(x,y) 関数テンプレートは、指定された位置で行列要素を操作するために使用され、関数が返すデータ型を使用時に指定する必要があります。
image.at(i,j) = 255;
iamge.atcv:Vec3b(i,j)[チャネル] = 値;

ヒント: OpenCV のカラー イメージのチャネル配置は RGB ではなく BGR であるため、outputImage.at(i,j)[0] は点の B コンポーネントを表します。

#include <iostream>
#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
 
using namespace cv;
using namespace std;
 
void colorReduce(Mat&intputImage,Mat&outputImage,int div){
    
    
 
    outputImage = intputImage.clone();
    int rows = intputImage.rows;
    int cols = intputImage.cols;
 
    //循环遍历图像中的元素
    for(int i = 0 ; i < rows; i++){
    
    
        for(int j = 0; j < cols; j++){
    
    
            outputImage.at<Vec3b>(i,j)[0] = outputImage.at<Vec3b>(i,j)[0] / div * div + div / 2;
            outputImage.at<Vec3b>(i,j)[1] = outputImage.at<Vec3b>(i,j)[1] / div * div + div / 2;
            outputImage.at<Vec3b>(i,j)[2] = outputImage.at<Vec3b>(i,j)[2] / div * div + div / 2;
        }
    }
}

ピクセルにアクセスするためのイテレータ

STL ライブラリでの使用法と同様に、C++ に精通している読者は STL ライブラリについて理解しておく必要があります。ここでも、反復子を使用して画像内のピクセルにアクセスできます。

  • cv::MatIteratorcv::Vec3bit;
  • cv::Mat_cv:Vec3b::イテレータそれ;
//和上面同样的例子(减少图像中的像素)
void colorReduce(Mat&inputImage,Mat&outputImage,int div){
    
    
 
    outputImage = inputImage.clone();
    //模版指定类型(方法一)
    Mat_<Vec3b>::iterator it = inputImage.begin<Vec3b>();
    Mat_<Vec3b>::iterator itend = inputImage.end<Vec3b>();
    //方法二:指明cimage类型的方法之后,就可以不写begin和end的类型
    Mat_<Vec3b>cimage = outputImage;
    Mat_<Vec3b>::iterator itout = cimage.begin();
    Mat_<Vec3b>::iterator itoutend = cimage.end();
 
    for(;it != itend; itout ++,it ++){
    
    
        (*itout)[0] = (*it)[0] / div * div + div / 2;
        (*itout)[1] = (*it)[1] / div * div + div / 2;
        (*itout)[2] = (*it)[2] / div * div + div / 2;
    }
//    Mat_<Vec3b>::iterator it = outputImage.begin<Vec3b>();
//    Mat_<Vec3b>::iterator itend = outputImage.end<Vec3b>();
//    for(;it != itend; it ++){
    
    
//        (*it)[0] = (*it)[0] / div * div + div / 2;
//        (*it)[1] = (*it)[1] / div * div + div / 2;
//        (*it)[2] = (*it)[2] / div * div + div / 2;
//    }

}

画像ピクセルへのポインタ アクセス

cv::Mat は、指定された行データの最初のアドレスを取得するための prt(int i) 関数テンプレートを提供します。prt(int i) 関数を使用して、指定されたデータ型を返します。

  • 画像.prt(i);
//和上面同样的例子(减少图像中的像素)

void colorReduce(Mat&inputImage,Mat&outputImage,int div){
    
    
 
    outputImage = inputImage.clone();
    int rows = outputImage.rows;
    int cols = outputImage.cols * outputImage.channels();
 
    for(int i = 0; i < rows; i++){
    
    
        uchar*data = inputImage.ptr<uchar>(i);
        uchar*dataout = outputImage.ptr<uchar>(i);
        for(int j = 0; j < cols; j++){
    
    
            dataout[j] = dataout[j] / div * div + div / 2;
        }
    }
 
}

通常、画像の幅が占めるバイト数が 4 または 8 の整数倍でない場合、データは各行に埋められます。

ただし、画像をデータで埋める必要がない場合は、画像を 1 次元の配列とみなすことができます。cv::Mat クラスには、画像がデータで満たされているかどうかを検出する isContinuous 関数が用意されています。使用済み、完了、true を返します。

void colorReduce(Mat&inputImage,Mat&outputImage,int div){
    
    
 
    outputImage = inputImage.clone();
    int rows = outputImage.rows;
    int cols = outputImage.cols * outputImage.channels();
 
    if(outputImage.isContinuous()){
    
    
        cols = cols * rows;
        rows = 1;//1维数组
        cout<<"没有进行数据补齐"<<endl;
    }
 
    for(int i = 0; i < rows; i++){
    
    
        uchar*data = inputImage.ptr<uchar>(i);
        uchar*dataout = outputImage.ptr<uchar>(i);
        for(int j = 0; j < cols; j++){
    
    
            dataout[j] = dataout[j] / div * div + div / 2;
        }
    }
 
}

cv::Mat クラスの data 属性はデータ領域を指す符号なしポインタであるため、データ領域を指す操作は次のように実現できます。

uchar*data = image.data; ポインタを次の行に移動する操作: data += image.step;
j 行 i 列のピクセルのアドレスを取得します: data = image.data + j * image。ステップ + i
*image.elemSize();

void colorReduce(Mat&inputImage,Mat&outputImage,int div){
    
    
 
    outputImage = inputImage.clone();
    int rows = outputImage.rows;
    int cols = outputImage.cols;
 
    uchar*dataout = outputImage.data;
 
    for(int i = 0; i < rows; i++){
    
    
        for(int j = 0; j < cols; j++){
    
    
            *dataout = *dataout / div * div + div / 2;
            dataout++;//指向下一个像素点的值
        }
    }
 
}

行と列全体のピクセルの割り当て

对于整行或者整列像素值的赋值方式如下:

img.row(i).setTo(Scalar(255));//Scalar表示标量的意思

img.col(j).setTo(Scalar(255));

おすすめ

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