Opencv C++ 6. Grayscale transformation: linear transformation, grayscale inversion, logarithmic transformation, gamma transformation, (adaptive) histogram equalization

1. Principle of grayscale transformation:

The original image pixel gray value r is mapped to a gray value s through the transformation function T: s=T(r).

2. Grayscale transformation method:

  1. Linear transformation (brightness and contrast adjustment):

    • Principle: Linear transformation is a simple method of adjusting brightness and contrast by applying a linear transformation formula to the gray level of each pixel. Apply the formula output_pixel = input_pixel * alpha + beta to each pixel, where alpha controls contrast and beta controls brightness. Increase the alpha value to increase contrast, and increase the beta value to increase brightness.
  2. Log transformation:

    • Principle: Logarithmic transformation modifies each pixel value of the image by applying a logarithmic function. This transformation is suitable for enhancing the low gray levels of an image because it stretches the differences between low gray levels. The formula is output_pixel = c * log(1 + input_pixel), where c is the scaling constant.
  3. Gamma Correction:

    • Principle: Gamma correction modifies each pixel value of the image by applying a power function. Gamma correction can be used to adjust the contrast and brightness of an image. The formula is output_pixel = c * (input_pixel ^ gamma), where c is the scaling constant and gamma is the gamma value. Increasing the gamma value increases contrast.
  4. Histogram equalization:

    • Principle: Histogram equalization aims to stretch the gray level distribution of the image to make it more uniform. This is achieved by redistributing pixel values to increase the number of brightness levels. This helps enhance the contrast of the image and highlight details in the image. The principle of this method is to remap the cumulative distribution function of the image so that it becomes a uniform distribution.
  5. Adaptive Histogram Equalization:

    • Principle: Adaptive histogram equalization divides the image into small blocks, and then performs histogram equalization on each block. This makes the distribution of gray levels in different areas of the image more even, especially when the image has obvious brightness changes.

3. Linear transformation

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;
using namespace std;

int main() {
    //Load image
    Mat image = imread("D://lena.png");

    if (image.empty()) {
        cout << "Unable to load image" << endl;
        return -1;
    }

    // User-defined brightness and contrast parameters
    double alpha = 1.5; // control contrast
    int beta = 30; // control brightness

    // Linear transformation
    Mat adjusted_image = Mat::zeros(image.size(), image.type());

    for (int y = 0; y < image.rows; y + + ) {
        for (int x = 0; x < image.cols; x + + ) {
            for (int c = 0; c < image.channels(); c + + ) {
                adjusted_image.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(alpha * image.at<Vec3b>(y, x)[c] + beta);
            }
        }
    }

    // Display the original image and the adjusted image
    imshow("original image", image);
    imshow("Brightness and contrast adjusted image", adjusted_image);
    waitKey(0);

    return 0;
}

Function introduction:

 // Linear transformation
    Mat adjusted_image = Mat::zeros(image.size(), image.type());

Mat::zeros is a function in OpenCV that creates a matrix (image) and initializes all its elements to zero. In this particular case, Mat::zeros(image.size(), image.type()) is used to create an image with the same dimensions and number of channels as image matrix and initialize all its elements to zero.

Specific explanation:

  • Mat is a data structure used in OpenCV to represent images and matrices.
  • image.size() Returns the dimensions (number of rows and columns) of the original image image.
  • image.type() returns the data type and channel number information of the original image image.

Mat::zeros(image.size(), image.type()) will create an image with the same dimensions and number of channels as the original image image but with all pixels The values will be initialized to zero. This is to store the adjusted image in subsequent operations, since we want the output image to have pixel values all zero before performing the linear transformation.

In fact, Mat::zeros is often used in image processing to create matrices used to store intermediate or result images, ensuring that their initial values are zero. This helps avoid potentially junk values or unpredictable results.

    for (int y = 0; y < image.rows; y + + ) {
        for (int x = 0; x < image.cols; x + + ) {
            for (int c = 0; c < image.channels(); c + + ) {
                adjusted_image.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(alpha * image.at<Vec3b>(y, x)[c] + beta);
            }
        }
    }
  1. for (int y = 0; y < image.rows; y + + ): This is the outer loop used to iterate through each row of the image.

  2. for (int x = 0; x < image.cols; x + + ): This is the inner loop that iterates through each column (pixel) of the image.

  3. for (int c = 0; c < image.channels(); c++ ): This is the inner loop that iterates over the channels of the image (for example, for a color image, the channel might be B ,G,R).

  4. adjusted_image.at(y, x)[c] = saturate_cast(alpha * image.at(y, x)[c] + beta);: This line The code performs the actual linear transformation operation. Specifically, it does the following for each channel of each pixel:

    • image.at(y, x)[c]: This part of the code gets the current pixel position (y, x)< from the original image image The gray level of channel c at /code>.
    • alpha * image.at(y, x)[c] + beta: This is the formula for linear transformation. alpha controls contrast adjustment, and beta controls brightness adjustment. Brightness and contrast adjustments are achieved by multiplying alpha by the current pixel's gray level and adding beta.
    • saturate_cast(...): This is a saturation operation that ensures that the adjusted pixel value is between 0 and 255. If the result is less than 0, it will be truncated to 0; if the result is greater than 255, it will be truncated to 255.
    • adjusted_image.at(y, x)[c]: The final adjusted pixel value will be stored in adjusted_image at the same location (y, x) in channel c.

4. Grayscale inversion:

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
Mat image1, output_image, image1_gray; //Define input image, output image, grayscale image
image1 = imread("D://lena.png"); //Read image;
if (image1.empty())
{
cout << "Read error" << endl;
return -1;
}

cvtColor(image1, image1_gray, COLOR_BGR2GRAY); //Grayscale
imshow("image1_gray", image1_gray); //Display grayscale image

output_image = image1_gray.clone();
for (int i = 0; i < image1_gray.rows; i + + )
{
for (int j = 0; j < image1_gray.cols; j + + )
{
output_image.at<uchar>(i, j) = 255 - image1_gray.at<uchar>(i, j); //Grayscale inversion
}
}
imshow("output_image", output_image); //Display the inverted image


waitKey(0); //Pause, keep the image displayed, wait for the key to end
return 0;
}

The result is:

The original image is on the left and the reversed image is on the right

Function introduction:

cvtColor(image1, image1_gray, COLOR_BGR2GRAY);

The general syntax of the cvtColor function is as follows:

void cvtColor(InputArray src, OutputArray dst, int code, int dstCn = 0);

Here are some common code values and their meanings:

  • CV_BGR2GRAY: BGR to grayscale conversion.
  • CV_BGR2HSV: BGR to HSV (hue, saturation, lightness) conversion.
  • CV_BGR2Lab: BGR to Lab conversion.
  • CV_BGR2YUV: BGR to YUV conversion.
  • CV_RGB2BGR: RGB to BGR conversion.
  • CV_GRAY2BGR: Grayscale to BGR conversion.

What is selected in this code is CV_BGR2GRAY, which converts BGR into grayscale.

output_image = image1_gray.clone();
for (int i = 0; i < image1_gray.rows; i + + )
{
for (int j = 0; j < image1_gray.cols; j + + )
{
output_image.at<uchar>(i, j) = 255 - image1_gray.at<uchar>(i, j); //Grayscale inversion
}
}
  1. output_image = image1_gray.clone();: First, create an output image output_image with the same size and type as the input image image1_gray, and It is initialized to be the same as the input image.

  2. Next, the program uses nested loops to iterate over each pixel in the input image image1_gray.

  3. output_image.at(i, j) = 255 - image1_gray.at(i, j);: In the inner loop, for each pixel (i, j ), which does the following:

    • image1_gray.at(i, j): Gets the grayscale value at pixel (i, j) from the input image. at(i, j) indicates that the pixel value is an unsigned character type (8-bit grayscale image).
    • 255 - image1_gray.at(i, j): Subtract 255 from the obtained gray value to achieve gray inversion. This causes lighter pixels to become darker and darker pixels to become lighter, inverting the appearance of the image.

Through this process, the grayscale value of each pixel in the input image is inverted, and the final result is stored in output_image. This operation can be used to create a negative effect or to convert a negative into a positive to achieve special effects on an image.

5. Gamma correction

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;
using namespace std;

int main() {
    //Load image
    Mat image = imread("D://lena.png");

    if (image.empty()) {
        cout << "Unable to load image" << endl;
        return -1;
    }

    // gamma value
    double gamma = 2; // Greater than or equal to 0, less than 0 is black.

    // Gamma correction
    Mat gamma_corrected_image = Mat::zeros(image.size(), image.type());

    for (int y = 0; y < image.rows; y + + ) {
        for (int x = 0; x < image.cols; x + + ) {
            for (int c = 0; c < image.channels(); c + + ) {
                double pixel_value = image.at<Vec3b>(y, x)[c] / 255.0;
                double corrected_value = pow(pixel_value, gamma) * 255.0;
                gamma_corrected_image.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(corrected_value);
            }
        }
    }

    // Display original image and gamma corrected image
    imshow("original image", image);
    imshow("Gamma corrected image", gamma_corrected_image);
    waitKey(0);

    return 0;
}

Rendering:

6. Logarithmic transformation

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <cmath>

using namespace cv;
using namespace std;

int main() {
    //Load image
    Mat image = imread("D://lena.png");

    if (image.empty()) {
        cout << "Unable to load image" << endl;
        return -1;
    }

    // Logarithmic transformation parameters
    double c = 1.0; // constant
    double gamma = 0.5; // Parameters of logarithmic transformation

    // Logarithmic transformation
    Mat log_transformed_image = Mat::zeros(image.size(), image.type());

    for (int y = 0; y < image.rows; y + + ) {
        for (int x = 0; x < image.cols; x + + ) {
            for (int c = 0; c < image.channels(); c + + ) {
                double pixel_value = image.at<Vec3b>(y, x)[c] / 255.0;
                double corrected_value = c * log(1 + pixel_value) / log(1 + gamma);
                log_transformed_image.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(corrected_value * 255.0);
            }
        }
    }

    // Display the original image and the logarithmically transformed image
    imshow("original image", image);
    imshow("Logarithmically transformed image", log_transformed_image);
    waitKey(0);

    return 0;
}

Rendering:

7. Histogram equalization

In this example, we load an image and load it as a grayscale image using the IMREAD_GRAYSCALE mode. Then, we use the equalizeHist function to perform histogram equalization to enhance the contrast of the image.

Histogram equalization is a simple yet effective method that can improve the contrast of an image by making the pixel values in an image more evenly distributed. This example demonstrates how to use OpenCV to implement histogram equalization to improve the visual quality of images.

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;
using namespace std;

int main() {
    //Load image
    Mat image = imread("D://lena.png", IMREAD_GRAYSCALE); // Load the image in grayscale mode

    if (image.empty()) {
        cout << "Unable to load image" << endl;
        return -1;
    }

    // Histogram equalization
    Mat equalized_image;
    equalizeHist(image, equalized_image);

    // Display the original image and the equalized image
    imshow("original image", image);
    imshow("image after histogram equalization", equalized_image);
    waitKey(0);

    return 0;
}

Rendering:

Why do we need to convert the image to grayscale mode before histogram equalization?

Histogram equalization is usually used for grayscale image processing, rather than color images, mainly for the following reasons:

  1. Simplified processing: Histogram equalization is a very basic and common image enhancement technique. In grayscale images, each pixel has only one grayscale value, so the processing is relatively simple. When processing color images, histogram equalization needs to be performed on each channel separately, adding complexity.

  2. Principle of histogram equalization: The core idea of histogram equalization is to stretch and expand the pixel value range of the image by redistributing pixel values to make the histogram of the image more uniform. In a grayscale image, this means adjusting the image's gray levels so that they are more evenly distributed between 0 and 255. In color images, this operation needs to be done separately for each channel.

  3. Color information redundancy: Color images contain more information, including color and brightness information. In some cases, only the brightness information needs to be equalized since the color information may not need to be changed. By converting a color image to grayscale, you can better control the effects of equalization to maintain the overall appearance of the image.

  4. Common applications: Histogram equalization is commonly used in applications such as medical image processing, computer vision, and image enhancement, which often use grayscale images. Therefore, in these scenarios, histogram equalization is often applied directly to grayscale images to improve contrast.

Although histogram equalization is usually used for grayscale images, there are also extended methods for color images, such as equalizing the luminance channel while leaving the color information unchanged. This type of method is often called color histogram equalization or color equalization. In this case, luminance information is processed, while color information is preserved.

8. Adaptive histogram equalization

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;
using namespace std;

int main() {
    //Load image
    Mat image = imread("D://lena.png", IMREAD_GRAYSCALE); // Load the image in grayscale mode

    if (image.empty()) {
        cout << "Unable to load image" << endl;
        return -1;
    }

    // Adaptive histogram equalization
    Mat adaptive_equalized_image;
    equalizeHist(image, adaptive_equalized_image);

    // Display the original image and the image after adaptive histogram equalization
    imshow("original image", image);
    imshow("Image after adaptive histogram equalization", adaptive_equalized_image);
    waitKey(0);

    return 0;
}

In this example, we load an image and load it as a grayscale image using the IMREAD_GRAYSCALE mode. We then use the equalizeHist function to perform adaptive histogram equalization to enhance the contrast of the image.

Adaptive histogram equalization is an improved histogram equalization method that applies equalization separately to different image areas to cope with lighting differences. This example demonstrates how to use OpenCV to implement adaptive histogram equalization to improve the visual quality of images.

-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --------

syntaxbug.com © 2021 All Rights Reserved.