Accessing pixels

Apart from using an ROI to access the pixels in a rectangular region of an image, as we did in the previous sections, there are a few other methods for achieving the same goal or even for accessing individual pixels of an image. To be able to access any single pixel in an image (in other words, a Mat object), you can use the at function, as seen in the following example:

image.at<TYPE>(R, C) 

In the preceding example, in the usage of the at function, TYPE must be replaced with a valid type name that is in accordance with the number of channels and depth of the image. R must be replaced with the row number, and C with the column number of the pixels we want to have access to. Notice that this is slightly different from the usual pixel-access methods in many libraries, in which the first parameter is X (or left) and the second parameter is Y (or top). So basically, the parameters appear reversed here. Here are some examples of accessing individual pixels in different types of Mat objects.

Accessing a pixel in a single-channel Mat object with 8-bit integer elements (grayscale images) is done as follows:

image.at<uchar>(R, C)

Accessing a pixel in a single-channel Mat object with floating-point elements is done as follows:

image.at<float>(R, C) 

Access a pixel in a three-channel Mat object with 8-bit integer elements as follows:

image.at<Vec3b>(R, C) 

In the preceding code, the Vec3b (vector of 3 bytes) type is used. This and various other similar vector types are defined in OpenCV for convenience. Here is the pattern of the OpenCV Vec types that you can use with the at function, or for any other purposes:

Vec<N><Type> 

<N> can be replaced with 2, 3, 4, 6, or 8 (or omitted in the case of 1) and it corresponds to the number of channels in a Mat object. <Type>, on the other hand, can be one of the following, which represent the type of the data stored in each channel of each pixel:

  • b for uchar (unsigned char)
  • s for short (signed word)
  • w for ushort (unsigned word)
  • i for int
  • f for float
  • d for double

For instance, Vec4b can be used to access the pixels of a four-channel Mat object with the uchar elements, and Vec6f can be used to access the pixels of a six-channel Mat object with the float elements. It's important to note that the Vec type can be treated like an array to access individual channels too. Here's an example of how to access the second channel of a three-channel Mat object with the uchar elements:

image.at<Vec3b>(R, C)[1]

It's important to note that by access we mean both reading and writing to a pixel and its individual channels. For instance, the following example is one way to apply a sepia filter to an image:

for(int i=0; i<image.rows; i++) 
{ 
    for(int j=0; j<image.cols; j++) 
    { 
        int inputBlue = image.at<Vec3b>(i,j)[0]; 
        int inputGreen = image.at<Vec3b>(i,j)[1]; 
        int inputRed = image.at<Vec3b>(i,j)[2]; 
 
        int red = 
                inputRed * 0.393 + 
                inputGreen * 0.769 + 
                inputBlue * 0.189; 
 
        if(red > 255 ) red = 255; 
 
        int green = 
                inputRed * 0.349 + 
                inputGreen * 0.686 + 
                inputBlue * 0.168; 
 
        if(green > 255) green = 255; 
 
        int blue = 
                inputRed * 0.272 + 
                inputGreen * 0.534 + 
                inputBlue * 0.131; 
 
        if(blue > 255) blue = 255; 
 
        image.at<Vec3b>(i,j)[0] = blue; 
        image.at<Vec3b>(i,j)[1] = green; 
        image.at<Vec3b>(i,j)[2] = red; 
    } 
} 

First, a few things to note here are the rows and cols members of the image, which basically represent the number of rows (or height) and the number of columns (or width) in it. Also notice how the at function is used both to extract the values of channels and to write updated values into them. Don't worry about the values used in this example to multiply and get the correct sepia tone, as they are specific to the tone itself, and essentially any type of operation can be applied to the individual pixels to change them.

The following image depicts the result of applying the preceding example code on a three-channel color image (left—original image, rightfiltered image):

Another method of accessing the pixels in an image is by using the forEach function of the Mat class. forEach can be used to apply an operation on all pixels in parallel, instead of looping through them one by one. Here's a simple example that shows how forEach is used to divide the value of all pixels by 5, which would result in a darker image if it is executed on a grayscale image:

image.forEach<uchar>([](uchar &p, const int *) 
{ 
    p /= 5; 
}); 

In the preceding code, the second parameter, or the position parameter (which is not needed and therefore omitted here) is the pointer to the position of the pixel.

Using the previous for loop, we would need to write the following:

for(int i=0; i<image.rows; i++) 
    for(int j=0; j<image.cols; j++) 
        image.at<uchar>(i,j) /= 5; 

OpenCV also allows the use of STL-like iterators to access or modify individual pixels in an image. Here's the same example but written using STL-like iterators:

MatIterator_<uchar> it_begin = image.begin<uchar>(); 
MatIterator_<uchar> it_end = image.end<uchar>(); 
for( ; it_begin != it_end; it_begin++) 
{ 
    *it_begin /= 5; 
}

It's interesting to note that the same operation in all of the preceding three examples can also be done by using the following simple statement:

image /= 5; 

This is because the Mat object in OpenCV treats this statement as an element-wise divide operation, which we'll learn more about it in the upcoming chapters. The following image depicts the result of applying the preceding examples to a grayscale image (left—original image, rightmodified image):

Obviously, forEach, the C++ for loop, and STL-like iterators can all be used to access and modify the pixels within a Mat object. We'll suffice to the functions and members discussed in this section about the Mat class, but make sure to explore the huge set of functionalities it provides to work with images and their underlying properties in an efficient way.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.157.197