📜 ⬆️ ⬇️

Implementation of the RGB-algorithm for changing the image contrast



While working on a program designed to process a video stream, it became necessary to implement an algorithm for changing the contrast of an image.

Since the program was designed for video processing, the implementation required high performance, including the ability to process Full HD video resolution. The code was written in C ++ using the OpenMP library.
')


There are several algorithms for changing the contrast, some of which are discussed in this article [1].

Consider the RGB contrast change algorithm.
First, we calculate the average brightness value of the image lAB. We use the OpenMP directive to parallelize the loop:
#pragma omp parallel for private(valueB,valueG,valueR) reduction(+:lAB) schedule(static,1) for (int j = 0; j < ptrImage->imageSize; j = j+3) { valueB = ptrImage->imageData[j]; valueG = ptrImage->imageData[j+1]; valueR = ptrImage->imageData[j+2]; lAB += (int)(valueR * 0.299 + valueG * 0.587 + valueB * 0.114); } //  lAB /= imageRows * imageCols; 

Then for each pixel of the image for each of the color components R, G, and B we must find the deviation from the average brightness value delta, and multiply this deviation by the gain (attenuation) of contrast k. Doing this directly above all the pixels of the image is too expensive. Therefore, given that we transform all the color components of a pixel in the same way, we introduce an array of 256 values ​​that will represent the palette for each color component. The array index corresponds to the old color component value, and the array value to the converted one. Thus, applying the previously described transformations to change the contrast to the palette, we get:
 //  double k = 1.0 + correction / 100.0; for (int i = 0; i < 256; i++) { int delta = (int)i - lAB; int temp = (int)(lAB + k *delta); if (temp < 0) temp = 0; if (temp >= 255) temp = 255; b[i] = (unsigned char)temp; } 


And further, we apply the new values ​​for the pixels of the entire image, matching the old value of the color component of the pixel with the new one, using the resulting palette array:
 #pragma omp parallel for firstprivate(b) for (int j = 0; j < ptrImage->imageSize; j++) { unsigned char value = ptrImage->imageData[j]; ptrImage->imageData[j] = (unsigned char)b[value]; } 

All source code for the function to change the contrast:
 const int L = 256; void AddContrastFilter(IplImage* ptrImage, int _correction) { //     4,      omp_set_num_threads(4); int correction = _correction; // int b[L]; //    int imageRows = ptrImage->height; int imageCols = ptrImage->width; int lAB = 0; unsigned char valueB = 0; unsigned char valueG= 0; unsigned char valueR= 0; //    #pragma omp parallel for private(valueB,valueG,valueR) reduction(+:lAB) schedule(static,1) for (int j = 0; j < ptrImage->imageSize; j = j+3) { valueB = ptrImage->imageData[j]; valueG = ptrImage->imageData[j+1]; valueR = ptrImage->imageData[j+2]; lAB += (int)(valueR * 0.299 + valueG * 0.587 + valueB * 0.114); } //    lAB /= imageRows * imageCols; //  double k = 1.0 + correction / 100.0; //RGB    for (int i = 0; i < L; i++) { int delta = (int)i - lAB; int temp = (int)(lAB + k *delta); if (temp < 0) temp = 0; if (temp >= 255) temp = 255; b[i] = (unsigned char)temp; } #pragma omp parallel for firstprivate(b) for (int j = 0; j < ptrImage->imageSize; j++) { unsigned char value = ptrImage->imageData[j]; ptrImage->imageData[j] = (unsigned char)b[value]; } return 0; } 

It turned out that changing the contrast of a Full HD frame on a four-core Intel Xeon processor takes about 8 ms.

Links


1. Contrast Conversion in Software: http://www.kweii.com/site/color_theory/Contrast100_en.pdf

Source: https://habr.com/ru/post/139428/


All Articles