Image processing refers to digital processing of any two-dimensional data (a picture) by a computer by applying signal processing methods. Image processing has a broad spectrum of applications, such as image representation, image enhancement or sharpening, image restoration by means of filtering, and geometrical correction. These applications are usually the first stage and input to the following stages in a computer vision system. In OpenCV, there is a specific module, imgproc
, for image processing. In this chapter, we will cover the most important and frequently used methods available in the library, that is, pixel-level access, histogram manipulation, image equalization, brightness and contracts modeling, color spaces, filtering, and arithmetic and geometrical transforms.
One of the most fundamental operations in image processing is pixel-level access. Since an image is contained in the Mat
matrix type, there is a generic access form that uses the at<>
template function. In order to use it, we have to specify the type of matrix cells, for example:
Mat src1 = imread("stuff.jpg", CV_LOAD_IMAGE_GRAYSCALE); uchar pixel1=src1.at<uchar>(0,0); cout << "First pixel: " << (unsigned int)pixel1 << endl; Mat src2 = imread("stuff.jpg", CV_LOAD_IMAGE_COLOR); Vec3b pixel2 = src2.at<Vec3b>(0,0); cout << "First pixel (B):" << (unsigned int)pixel2[0] << endl; cout << "First pixel (G):" << (unsigned int)pixel2[1] << endl; cout << "First pixel (R):" << (unsigned int)pixel2[2] << endl;
Note that color images use the Vec3b
type, which is an array of three unsigned chars. Images with a fourth alpha (transparency) channel would be accessed using the type Vec4b
. The Scalar
type represents a 1 to 4-element vector and can also be used in all these cases. Note that at<>
can be also used to change pixel values (that is, on the left-hand side of an assignment).
Apart from pixel access, there are a number of common operations for which we should know the corresponding snippets. The following table shows these common operations:
Operation |
Code example |
---|---|
Obtain size of matrix |
Size siz=src.size(); cout << "width: " << siz.width << endl; cout << "height: " << siz.height << endl;
|
Obtain number of channels |
int nc=src.channels();
|
Obtain pixel data type |
int d=src.depth();
|
Set matrix values |
src.setTo(0); //for one-channel src
Or
src.setTo(Scalar(b,g,r)); // for three-channel src
|
Create a copy of the matrix |
Mat dst=src.clone();
|
Create a copy of the matrix (with optional mask) |
src.copy(dst, mask);
|
Reference a submatrix |
Mat dst=src(Range(r1,r2),Range(c1,c2));
|
Create a new matrix from a submatrix (that is, image crop) |
Rect roi(r1,c2, width, height); Mat dst=src(roi).clone();
|
Note the difference in the last two rows: in the last row, a new matrix is created. The case of the penultimate row only creates a reference to a submatrix within src
, but data is not actually copied.
The most common operations, including additional iterator-based pixel access methods, are summarized in the OpenCV 2.4 Cheat Sheet, which can be downloaded from http://docs.opencv.org/trunk/opencv_cheatsheet.pdf.