Recherche…


Remarques

Veillez à bien connaître le type de cv::Mat vous parlez. Par exemple, si vous avez un cv::Mat de type CV_8UC3 , mais que vous y accédez avec image.at<uchar>(r,c) aucune erreur ne se produira, mais votre programme aura un comportement inattendu.

Accédez à des valeurs de pixel individuelles avec cv :: Mat :: at ()

Pour accéder aux valeurs de pixels dans un objet OpenCV cv::Mat , vous devez d'abord connaître le type de votre matrice.

Les types les plus courants sont:

  • CV_8UC1 pour les images en niveaux de gris à 1 canal sur 8 bits;
  • CV_32FC1 pour les images en niveaux de gris à 1 canal à virgule flottante 32 bits;
  • CV_8UC3 pour les images couleur à 3 canaux à 8 bits; et
  • CV_32FC3 pour les images couleur à 3 canaux en virgule flottante 32 bits.

Le paramètre par défaut avec cv::imread créera une matrice CV_8UC3 .

Pour accéder aux pixels individuels, le moyen le plus sûr, mais pas le plus efficace, consiste à utiliser la méthode cv::Mat::at<T>(r,c)r est la ligne de la matrice et c la colonne . L'argument du modèle dépend du type de la matrice.

Disons que vous avez une cv::Mat image . Selon son type, la méthode d'accès et le type de couleur de pixel seront différents.

  • Pour CV_8UC1 : uchar pixelGrayValue = image.at<uchar>(r,c) .
  • Pour CV_8UC3 : cv::Vec3b pixelColor = image.at<cv::Vec3b>(r,c) . L'objet cv::Vec3b représente un triplet de valeurs uchar (entiers compris entre 0 et 255).
  • Pour CV_32FC1 : float pixelGrayValue = image.at<float>(r,c) .
  • Pour CV_32FC3 : cv::Vec3f pixelColor = image.at<cv::Vec3f>(r,c) . L'objet cv::Vec3f représente un triplet de valeurs float .

Notez qu'OpenCV représente les images dans l'ordre des lignes principales , comme par exemple Matlab ou la convention en Algèbre. Ainsi, si vos coordonnées de pixel sont (x,y) , vous accéderez au pixel en utilisant image.at<..>(y,x) .

Alternativement, at<> également prendre en charge l'accès via un seul argument cv::Point .
Dans ce cas, l'accès se fait en colonne majeure :

image.at<..>(cv::Point(x,y));

Consultez la documentation OpenCV pour plus de détails sur cette méthode.

Accès efficace aux pixels en utilisant cv :: Mat :: ptr aiguille

Si l'efficacité est importante, un moyen rapide d'itérer sur des pixels dans un objet cv::Mat consiste à utiliser sa méthode ptr<T>(int r) pour obtenir un pointeur sur le début de la ligne r (index basé sur 0).

Selon le type de matrice, le pointeur aura un modèle différent.

  • Pour CV_8UC1 : uchar* ptr = image.ptr<uchar>(r);
  • Pour CV_8UC3 : cv::Vec3b* ptr = image.ptr<cv::Vec3b>(r);
  • Pour CV_32FC1 : float* ptr = image.ptr<float>(r);
  • Pour CV_32FC3 : cv::Vec3f* ptr = image.ptr<cv::Vec3f>(r);

Cet objet ptr peut alors être utilisé pour accéder à la valeur de pixel sur la ligne r et la colonne c en appelant ptr[c] .

Pour illustrer cela, voici un exemple où nous chargeons une image à partir du disque et inversons ses canaux bleu et rouge, fonctionnant pixel par pixel:

#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;
}

Définition et obtention des valeurs de pixels d'une image grise en 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;
}

Accès aux pixels alternatif avec le Matiterator

Ce n'est pas la meilleure façon de parcourir les pixels. cependant, c'est mieux que cv :: Mat :: at <T>.

Supposons que vous ayez une image couleur dans votre dossier et que vous souhaitiez itérer chaque pixel de cette image et effacer les canaux vert et rouge (notez que ceci est un exemple, vous pouvez le faire de manière plus optimisée);

#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;
}

Pour compiler ceci avec Cmake:

cmake_minimum_required(VERSION 2.8)
project(Main)
find_package(OpenCV REQUIRED)
add_executable(Main main.cpp)
target_link_libraries(Main ${OpenCV_LIBS})

L'image originale: entrer la description de l'image ici

L'image traitée: entrer la description de l'image ici

Notez que nous ne touchons que le canal bleu.

Pour plus d'informations: http://docs.opencv.org/2.4/opencv_tutorials.pdf Page: 145

Accès aux pixels dans Mat

L'accès individuel aux pixels dans la structure OpenCV Mat peut être réalisé de plusieurs manières. Pour comprendre comment accéder, il est préférable d'apprendre d'abord les types de données.

Structures de base explique les types de données de base. CV_<bit-depth>{U|S|F}C(<number_of_channels>) est la structure de base d'un type. Parallèlement à cela, il est important de comprendre les structures Vec .

typedef Vec<type, channels> Vec< channels>< one char for the type>

où type est l'un des uchar, short, int, float, double et les caractères de chaque type sont respectivement b, s, i, f, d .

Par exemple, Vec2b indique un unsigned char vector of 2 channels .

Considérez Mat mat(R,C,T) où R est #rows, C est #cols et T est le type. Voici quelques exemples d’accès à la coordonnée (i, j) de mat :

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

Notez qu'il est très important d'entrer un type correct dans <...> , sinon vous pouvez avoir une erreur d'exécution ou des résultats indésirables.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow