Manipulating the Pixels
In order to build computer vision applications, you need to be able to access the image content and, eventually, modify or create images. This chapter will teach you how to manipulate the picture elements (also known as pixels). You will learn how to scan an image and process each of its pixels. You will also learn how to do this efficiently, since even images of modest dimensions can contain hundreds of thousands of pixels.
Fundamentally, an image is a matrix of numerical values. This is why, as we learned in Chapter 1, Playing with Images, OpenCV 4 manipulates them using the cv::Mat data structure. Each element of the matrix represents one pixel. For a gray-level image (a black-and-white image), pixels are unsigned 8-bit values where 0 corresponds to black and 255 corresponds to white. In the case of color images, three primary color values are required in order to reproduce the different visible colors. This is a consequence of the fact that our human visual system is trichromatic; three types of cone cells on our retinas convey color information to our brains. This means that for a color image, three values must be associated with each pixel. In photography and digital imaging, the commonly used primary color channels are red, green, and blue. A matrix element is, therefore, made up of a triplet of 8-bit values in this case.
Note that even if 8-bit channels are generally sufficient, there are specialized applications where 16-bit channels are required (medical imaging, for example).
As we saw in the previous chapter, OpenCV also allows you to create matrices (or images) with pixel values of other types, for example, integer (CV_32U or CV_32S) and floating-point (CV_32F) numbers. These are very useful for storing, for example, intermediate values in some image-processing tasks. Most operations can be applied on matrices of any type; others require a specific type of work with only a given number of channels. Therefore, a good understanding of a function's or method's preconditions is essential in order to avoid common programming errors.
Throughout this chapter, we use the following color image as the input:
In this chapter, we will cover the following recipes:
- Accessing pixel values
- Scanning an image with pointers
- Scanning an image with iterators
- Writing efficient image-scanning loops
- Scanning an image with neighbor access
- Performing simple image arithmetic
- Remapping an image