OpenCV #001 Manipulating Image Pixels
Digital Image Processing using OpenCV (Python & C++)
Highlight: In this blog post, we will give an overview of what a pixel is, how a computer understands it and how pixels can be accessed and manipulated using OpenCV.
Tutorial Overview:
- What’s a Pixel?
- Coordinate System in an Image.
- Pixel access and manipulation in Python
- Pixel access and manipulation in C++
1. What’s a Pixel?
When we talk about video files, we are mainly concerned with quality and resolution. That is why most of us have a full HD, 4k Ultra HD, 8k Ultra HD. However, if we zoom in a photo, we will see small tiny square boxes close to each other. All these tiny boxes collectively represent an image, and they are known as pixels. So now, what is a pixel?
In a few words, a pixel is a small element of a picture. Each pixel represents a color which is a combination of three color channels: red, green and blue. With a million combination of these colours, we can represent any colour and any image. Wow!
In computers, images are commonly stored as matrices. Every pixel has 3 intensity values for red, green and blue (RGB). To represent a single channel intensity, we will use values from 0-255, and we use 8 bits for a color channel per pixel. For grayscale images, on the other hand, we use values from 0-255 to represent gray intensities: 0-black and 255-white.
2. Coordinate System in an Image
An image can be seen as a grid of pixels. A coordinate system can be used to access each pixel. For example, let’s pick 2 coordinate points \((x,y) \) on the grid, \((0,0)\). This corresponds to the upper left corner of the image and as the values for x and y increase we move down and to the right.
Note: pixels are accessed with \((x, y)\) coordinates. The \(x \) value represents the columns and the \(y \) value represents the rows.
After that has been clarified, it’s also good to know that OpenCV reads these channel order \((R, G, B)\), in reverse \((B, G, R)\). Now, let’s see how we can access and manipulate pixels on an image.
3. Pixel access and manipulation in Python
4. Pixel access and manipulation in C++
#include <opencv2/opencv.hpp> //Include file for every supported OpenCV function. Hint: Slow to compile.
using namespace cv; // optional
using namespace std;
int main ( int argc, char** argv ) {
// initialization
cv::Mat image;
int x=0, y=0;
// place an image in the working folder
image = cv::imread("car.jpg", IMREAD_COLOR );
// we will use this command to show an image.
// the first argument is the title of the window, the second one is the loaded image (MAT format)
cv::imshow("Window 1", image);
// we wait for a key to be pressed, and then we exit.
cv::waitKey(0);
// the following piece of code reads a single pixel value
// then it prints it.
// 3 channel image with BGR color (type 8UC3)
// the values can be stored in "int" or in "uchar". Here int is
//used.
cv::Vec3b intensity = image.at<Vec3b>(y, x);
float blue = intensity.val[0];
float green = intensity.val[1];
float red = intensity.val[2];
std::cout << "Blue:" << blue << std::endl;
std::cout << "Green:" << green << std::endl;
std::cout << "Red:" << red << std::endl;
// changing a single pixel color at the location (x,y)
// get a pixel
cv::Vec3b color = image.at<Vec3b>(Point(x,y));
color[0]=0;
color[1]=255;
color[2]=0;
// set a pixel back to the image
image.at<Vec3b>(Point(x,y)) = color;
cv::imshow("Changed one pixel value", image);
waitKey(0);
// change the part of the image into a certain color
// this code snippet will loop over an upper-top rectangle,
// it will access each pixel and change its value.
// Following OpenCV's format BGR, we will get green pixels.
// That is, a green rectangle in the upper top image.
for (x=0; x<100; x++) {
for (y=0; y<100; y++ ){
// get a pixel
cv::Vec3b color = image.at<Vec3b>(Point(x,y));
color[0]=0;
color[1]=255;
color[2] =0;
// set a pixel back to the image
image.at<Vec3b>(Point(x,y)) = color;
}
}
cv::imshow("Changed a part of the image", image);
waitKey(0);
// Saving the image
cv::imwrite( "new_image.jpg", image);
return 0;
}
Explanation
We imported the necessary libraries, loaded the image from the disk and displayed it.
Next, at the top left corner of the frame, coordinate \((0, 0) \), we replaced the original pixel value into a green pixel. However, this cannot be easily seen, except when we zoom closely at the image. Therefore, we selected a \(100×100\)-pixel region from \((0,0)\) to \((99,99)\) and repainted the color with this range to all green.
After that, the bottom image shows that we have successfully drawn a green square in our image. That is, we have replaced all pixels intensity values that fit that rectangle with green pixels.
Summary
To sum up, we have learned what a pixel is, how to access and manipulate the pixels in an image using NumPy’s built-in array slicing functionality. In addition, we gave an overview of how this can be done in C++ as well.
In the next post, we will see how to read, write and display videos using OpenCV.