opencv
Pixeltoegang
Zoeken…
Opmerkingen
Let op het type cv::Mat
u te maken heeft. Als u bijvoorbeeld een cv::Mat
van het type CV_8UC3
, maar deze image.at<uchar>(r,c)
met image.at<uchar>(r,c)
zal er geen fout optreden, maar uw programma zal onverwacht gedrag vertonen.
Toegang tot individuele pixelwaarden met cv :: Mat :: at ()
Om toegang te krijgen tot pixelwaarden in een OpenCV cv::Mat
object, moet u eerst het type van uw matrix weten.
De meest voorkomende soorten zijn:
-
CV_8UC1
voor 8-bit 1-kanaals grijswaardenafbeeldingen; -
CV_32FC1
voor 32-bit drijvende-komma 1-kanaals grijswaardenafbeeldingen; -
CV_8UC3
voor 8-bit 3-kanaals kleurenafbeeldingen; en -
CV_32FC3
voor 32-bit drijvende-komma 3-kanaals kleurenafbeeldingen.
De standaardinstelling met cv::imread
maakt een CV_8UC3
matrix.
Om toegang te krijgen tot individuele pixels, is de veiligste, hoewel niet de meest efficiënte, het gebruik van cv::Mat::at<T>(r,c)
methode waarbij r
de rij van de matrix is en c
de kolom is . Het sjabloonargument hangt af van het type matrix.
Laten we zeggen dat je een cv::Mat image
. Afhankelijk van het type zullen de toegangsmethode en het pixelkleurtype verschillen.
- Voor
CV_8UC1
:uchar pixelGrayValue = image.at<uchar>(r,c)
. - Voor
CV_8UC3
:cv::Vec3b pixelColor = image.at<cv::Vec3b>(r,c)
. Het objectcv::Vec3b
vertegenwoordigt een triplet vanuchar
waarden (gehele getallen tussen 0 en 255). - Voor
CV_32FC1
:float pixelGrayValue = image.at<float>(r,c)
. - Voor
CV_32FC3
:cv::Vec3f pixelColor = image.at<cv::Vec3f>(r,c)
. Decv::Vec3f
object vertegenwoordigt een triplet vanfloat
waarden.
Merk op dat OpenCV afbeeldingen in rij- hoofdvolgorde weergeeft, zoals bijvoorbeeld Matlab of als de conventie in Algebra. Als uw image.at<..>(y,x)
dus (x,y)
, hebt u toegang tot de pixel met image.at<..>(y,x)
.
Als alternatief, at<>
ook ondersteuning via een enkel cv::Point
argument.
In dit geval gebeurt de toegang in kolom-major :
image.at<..>(cv::Point(x,y));
Bekijk de OpenCV-documentatie voor meer informatie over deze methode.
Efficiënte pixeltoegang met cv :: Mat :: ptr wijzer
Als efficiëntie belangrijk is, is een snelle manier om pixels in een cv::Mat
object te herhalen, de ptr<T>(int r)
-methode te gebruiken om een aanwijzer naar het begin van rij r
(op 0 gebaseerde index) te verkrijgen.
Afhankelijk van het matrixtype heeft de aanwijzer een ander sjabloon.
- Voor
CV_8UC1
:uchar* ptr = image.ptr<uchar>(r);
- Voor
CV_8UC3
:cv::Vec3b* ptr = image.ptr<cv::Vec3b>(r);
- Voor
CV_32FC1
:float* ptr = image.ptr<float>(r);
- Voor
CV_32FC3
:cv::Vec3f* ptr = image.ptr<cv::Vec3f>(r);
Dit ptr
object kan vervolgens worden gebruikt om toegang te krijgen tot de pixelwaarde op rij r
en kolom c
door ptr[c]
aan te roepen.
Om dit te illustreren, is hier een voorbeeld waarin we een afbeelding van schijf laden en de blauwe en rode kanalen omkeren, die pixel voor pixel werken:
#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;
}
Pixelwaarden van een grijze afbeelding instellen en ophalen in 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;
}
Alternatieve pixeltoegang met Matiterator
Het is niet de beste manier om door de pixels te bladeren; het is echter beter dan cv :: Mat :: op <T>.
Laten we aannemen dat u een kleurenafbeelding in uw map hebt en dat u elke pixel van deze afbeelding wilt herhalen en groene en rode kanalen wilt wissen (dit is een voorbeeld, u kunt dit op meer geoptimaliseerde manieren doen);
#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;
}
Om dit te compileren met Cmake:
cmake_minimum_required(VERSION 2.8)
project(Main)
find_package(OpenCV REQUIRED)
add_executable(Main main.cpp)
target_link_libraries(Main ${OpenCV_LIBS})
Merk op dat we niet alleen het blauwe kanaal aanraken.
Voor meer informatie: http://docs.opencv.org/2.4/opencv_tutorials.pdf Pagina: 145
Pixeltoegang in Mat
Individuele pixeltoegang in OpenCV Mat-structuur kan op meerdere manieren worden bereikt. Om te begrijpen hoe toegang te krijgen, is het beter om eerst de gegevenstypen te leren.
Basic Structures verklaart de basis datatypes. Kort CV_<bit-depth>{U|S|F}C(<number_of_channels>)
is CV_<bit-depth>{U|S|F}C(<number_of_channels>)
de basisstructuur van een type. Daarnaast is het belangrijk om Vec
structuren te begrijpen.
typedef Vec<type, channels> Vec< channels>< one char for the type>
waarbij type een is van uchar, short, int, float, double
en de tekens voor elk type respectievelijk b, s, i, f, d
zijn.
Vec2b geeft bijvoorbeeld een unsigned char vector of 2 channels
.
Beschouw Mat mat(R,C,T)
waarbij R # rijen is, C # cols is en T type is. Enkele voorbeelden voor toegang tot de (i, j) coördinaat van mat
zijn:
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
Houd er rekening mee dat het zeer cruciaal is om het juiste type in <...>
, anders kunt u een runtime-fout of ongewenste resultaten hebben.