opencv
ピクセルアクセス
サーチ…
備考
あなたが扱っているcv::Mat
タイプに注意してください。たとえば、 CV_8UC3
タイプのcv::Mat
があるimage.at<uchar>(r,c)
アクセスすると、エラーは発生しませんが、プログラムに予期しない動作が発生します。
cv :: Mat :: atで個々のピクセル値にアクセスする ()
OpenCV cv::Mat
オブジェクトのピクセル値にアクセスするには、まず行列の型を知る必要があります。
最も一般的なタイプは次のとおりです。
- 8ビットの1チャネルグレースケール画像の場合は
CV_8UC1
、 - 32ビット浮動小数点1チャンネルグレースケール画像用の
CV_32FC1
。 -
CV_8UC3
(8ビット3チャネルカラー画像用)そして - 32ビット浮動小数点3チャネルカラー画像用の
CV_32FC3
。
cv::imread
のデフォルト設定では、 CV_8UC3
行列が作成されます。
個々のピクセルにアクセスするには、最も効率的ではありませんが、 cv::Mat::at<T>(r,c)
メソッドを使用しますr
は行列の行 、 c
は列です。テンプレートの引数は、行列の型によって異なります。
あなたはcv::Mat image
を持っているとしましょう。そのタイプに応じて、アクセス方法とピクセルカラータイプが異なります。
-
CV_8UC1
:uchar pixelGrayValue = image.at<uchar>(r,c)
。 -
CV_8UC3
:cv::Vec3b pixelColor = image.at<cv::Vec3b>(r,c)
。cv::Vec3b
オブジェクトは、3つのuchar
値(0〜255の整数)を表します。 -
CV_32FC1
:float pixelGrayValue = image.at<float>(r,c)
。 -
CV_32FC3
:cv::Vec3f pixelColor = image.at<cv::Vec3f>(r,c)
。cv::Vec3f
オブジェクトは、float
値の3つ組を表します。
OpenCVはMatlabのような行優先順位の画像を表すか、または代数の慣習として表現することに注意してください。したがって、ピクセル座標が(x,y)
場合、 image.at<..>(y,x)
を使用してピクセルにアクセスします。
あるいは、 at<>
単一のcv::Point
引数を介してアクセスをサポートすることもできます。
この場合、アクセスはcolumn-majorで実行されます 。
image.at<..>(cv::Point(x,y));
このメソッドの詳細については、 OpenCVのドキュメントを参照してください。
cv :: Mat :: ptrを使った効率的なピクセルアクセスポインタ
効率が重要な場合、 cv::Mat
オブジェクトのピクセルを素早く処理するには、 ptr<T>(int r)
メソッドを使用して、行r
の先頭(0から始まるインデックス)へのポインタを取得します。
マトリックスタイプによれば、ポインタは異なるテンプレートを有する。
-
CV_8UC1
:uchar* ptr = image.ptr<uchar>(r);
-
CV_8UC3
:cv::Vec3b* ptr = image.ptr<cv::Vec3b>(r);
-
CV_32FC1
:float* ptr = image.ptr<float>(r);
-
CV_32FC3
:cv::Vec3f* ptr = image.ptr<cv::Vec3f>(r);
次に、このptr
オブジェクトを使用して、 ptr[c]
呼び出して行r
と列c
ピクセル値にアクセスできます。
これを説明するために、ここではディスクから画像をロードし、青と赤のチャンネルを反転させ、ピクセル単位で操作する例を示します。
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
int main(int argc, char** argv) {
cv::Mat image = cv::imread("image.jpg", CV_LOAD_IMAGE_COLOR);
if(!image.data) {
std::cout << "Error: the image wasn't correctly loaded." << std::endl;
return -1;
}
// We iterate over all pixels of the image
for(int r = 0; r < image.rows; r++) {
// We obtain a pointer to the beginning of row r
cv::Vec3b* ptr = image.ptr<cv::Vec3b>(r);
for(int c = 0; c < image.cols; c++) {
// We invert the blue and red values of the pixel
ptr[c] = cv::Vec3b(ptr[c][2], ptr[c][1], ptr[c][0]);
}
}
cv::imshow("Inverted Image", image);
cv::waitKey();
return 0;
}
C ++でのグレー画像のピクセル値の設定と取得
// PixelAccessTutorial.cpp : Defines the entry point for the console
// Environment: Visual studio 2015, Windows 10
// Assumptions: Opecv is installed configured in the visual studio project
// Opencv version: OpenCV 3.1
#include "stdafx.h"
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<string>
#include<iostream>
int main()
{
cv::Mat imgOriginal; // input image
cv::Mat imgGrayscale; // grayscale of input image
std::cout << "Please enter an image filename : ";
std::string img_addr;
std::cin >> img_addr;
std::cout << "Searching for " + img_addr << std::endl;
imgOriginal = cv::imread(img_addr); // open image
if (imgOriginal.empty()) { // if unable to open image
std::cout << "error: image not read from file\n\n"; // show error message on command line
return(0); // and exit program
}
cv::cvtColor(imgOriginal, imgGrayscale, CV_BGR2GRAY); // convert to grayscale
const int channels = imgGrayscale.channels();
printf("Number of channels = %d", channels);
cv::Mat output ;
imgGrayscale.copyTo(output); // Just to make sure the Mat objects are of the same size.
//Set the threshhold to your desired value
uchar threshhold = 127;
if (channels == 1)
{
for (int x = 0; x<imgGrayscale.rows; x++) {
for (int y = 0; y<imgGrayscale.cols; y++) {
// Accesssing values of each pixel
if (imgGrayscale.at<uchar>(x, y) >= threshhold) {
// Setting the pixel values to 255 if it's above the threshold
output.at<uchar>(x, y) = 254;
}
else if (imgGrayscale.at<uchar>(x, y) < threshhold) {
// Setting the pixel values to 255 if it's below the threshold
output.at<uchar>(x, y) = 0;
}
else {
// Just in case
printf("The value at (%d, %d) are not right. Value: %d\n", x, y, imgGrayscale.at<uchar>(x, y));
}
}
}
}
else if (channels == 3)
{
// This is only for gray scale images
printf("\tThe image has 3 channels. The function does not support images with 3 channels.\n");
}
//Create windows to show image
cv::namedWindow("Gray scale", CV_WINDOW_AUTOSIZE);
cv::namedWindow("Binary", CV_WINDOW_AUTOSIZE);
cv::imshow("Gray scale", imgGrayscale);
cv::imshow("Binary", output);
cv::waitKey(0); // hold windows open until user presses a key
return 0;
}
Matiteratorによる代替ピクセルアクセス
これはピクセルを反復する最善の方法ではありません。しかし、それはcv :: Mat :: at <T>よりも優れています。
フォルダ内にカラー画像があり、この画像の各ピクセルを繰り返し、緑色と赤色のチャンネルを消去したいとします(これは一例であり、より最適化された方法で行うことができます)。
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
int main(int argc, char **argv)
{
// Create a container
cv::Mat im;
//Create a vector
cv::Vec3b *vec;
// Create an mat iterator
cv::MatIterator_<cv::Vec3b> it;
// Read the image in color format
im = cv::imread("orig1.jpg", 1);
// iterate through each pixel
for(it = im.begin<cv::Vec3b>(); it != im.end<cv::Vec3b>(); ++it)
{
// Erase the green and red channels
(*it)[1] = 0;
(*it)[2] = 0;
}
// Create a new window
cv::namedWindow("Resulting Image");
// Show the image
cv::imshow("Resulting Image", im);
// Wait for a key
cv::waitKey(0);
return 0;
}
これをCmakeでコンパイルするには:
cmake_minimum_required(VERSION 2.8)
project(Main)
find_package(OpenCV REQUIRED)
add_executable(Main main.cpp)
target_link_libraries(Main ${OpenCV_LIBS})
ブルーチャンネルには触れないことに注意してください。
詳細については、 http : //docs.opencv.org/2.4/opencv_tutorials.pdfを参照してください。
マットのピクセルアクセス
OpenCV Mat構造での個々のピクセルアクセスは、複数の方法で実現できます。アクセス方法を理解するには、最初にデータ型を学習することをお勧めします。
「基本構造」では、基本的なデータ型について説明します。まもなく、 CV_<bit-depth>{U|S|F}C(<number_of_channels>)
は型の基本構造です。それに加えて、 Vec
構造を理解することが重要です。
typedef Vec<type, channels> Vec< channels>< one char for the type>
typeはuchar, short, int, float, double
あり、それぞれの型の文字はそれぞれb, s, i, f, d
です。
たとえば、Vec2bはunsigned char vector of 2 channels
示しunsigned char vector of 2 channels
。
Mat mat(R,C,T)
考えてみましょう。Rは#rows、Cは#cols、Tは型です。 mat
(i、j)座標にアクセスするいくつかの例は次のとおりです。
2D:
If the type is CV_8U or CV_8UC1 ---- //they are alias
mat.at<uchar>(i,j) // --> This will give char value of index (i,j)
//If you want to obtain int value of it
(int)mat.at<uchar>(i,j)
If the type is CV_32F or CV_32FC1 ---- //they are alias
mat.at<float>(i,j) // --> This will give float value of index (i,j)
3D:
If the type is CV_8UC2 or CV_8UC3 or more channels
mat.at<Vec2b/Vec3b>(i,j)[k] // note that (k < #channels)
//If you want to obtain int value of it
(int)mat.at<uchar>(i,j)[k]
If the type is CV_64FC2 or CV_64FC3
mat.at<Vec2d/Vec3d>(i,j)[k] // note that k < #channels
<...>
に正しい型を入力することは非常に重要<...>
そうしないと、実行時エラーまたは望ましくない結果を得ることができます。