Automated Image Enhancement Tool for Low-Quality Photographs,C++
👤 Sharing: AI
```cpp
#include <iostream>
#include <opencv2/opencv.hpp> // Include OpenCV library
#include <algorithm> // For std::clamp
using namespace cv;
using namespace std;
// Function Declarations (to keep main cleaner)
Mat automaticWhiteBalance(const Mat& inputImage);
Mat histogramEqualization(const Mat& inputImage);
Mat unsharpMasking(const Mat& inputImage, float amount = 1.0, float radius = 1.0, int threshold = 0);
Mat adjustBrightnessContrast(const Mat& inputImage, double brightness = 0.0, double contrast = 1.0);
Mat reduceNoise(const Mat& inputImage, int strength = 3);
int main() {
// 1. Load the image
string imagePath;
cout << "Enter the path to your image: ";
cin >> imagePath;
Mat originalImage = imread(imagePath);
if (originalImage.empty()) {
cerr << "Error: Could not load image." << endl;
return -1;
}
// Display the original image
imshow("Original Image", originalImage);
waitKey(0); // Wait for a key press
// 2. Apply Image Enhancement Techniques
// a) Automatic White Balance (color correction)
Mat whiteBalancedImage = automaticWhiteBalance(originalImage);
imshow("White Balanced Image", whiteBalancedImage);
waitKey(0);
// b) Histogram Equalization (contrast enhancement)
Mat equalizedImage = histogramEqualization(whiteBalancedImage); // Using whiteBalanced as input
imshow("Histogram Equalized Image", equalizedImage);
waitKey(0);
// c) Unsharp Masking (sharpening)
Mat sharpenedImage = unsharpMasking(equalizedImage, 1.0, 1.0, 5); // Using equalized as input
imshow("Sharpened Image", sharpenedImage);
waitKey(0);
// d) Brightness and Contrast Adjustment
Mat adjustedImage = adjustBrightnessContrast(sharpenedImage, 10, 1.1); // Using sharpened as input
imshow("Brightness/Contrast Adjusted Image", adjustedImage);
waitKey(0);
// e) Noise Reduction
Mat denoisedImage = reduceNoise(adjustedImage, 3);
imshow("Denoised Image", denoisedImage);
waitKey(0);
// 3. Save the enhanced image (optional)
string outputPath = "enhanced_image.jpg";
imwrite(outputPath, denoisedImage);
cout << "Enhanced image saved to: " << outputPath << endl;
// Clean up
destroyAllWindows();
return 0;
}
// Function Definitions
// 1. Automatic White Balance (Simple Grey World Assumption)
Mat automaticWhiteBalance(const Mat& inputImage) {
Mat image = inputImage.clone(); // Create a copy to avoid modifying the original
Scalar meanColor = mean(image); // Calculate the average color of the entire image.
double avgR = meanColor[2]; // Red
double avgG = meanColor[1]; // Green
double avgB = meanColor[0]; // Blue
// Calculate scaling factors to normalize the average color towards gray
double scaleR = avgG / avgR;
double scaleB = avgG / avgB;
// Apply the scaling to each channel
for (int y = 0; y < image.rows; ++y) {
for (int x = 0; x < image.cols; ++x) {
Vec3b& pixel = image.at<Vec3b>(y, x); // Get a reference to the pixel
pixel[2] = saturate_cast<uchar>(pixel[2] * scaleR); // Red
pixel[0] = saturate_cast<uchar>(pixel[0] * scaleB); // Blue
// Green channel remains mostly unchanged, as it's the reference.
}
}
return image;
}
// 2. Histogram Equalization (Contrast Enhancement)
Mat histogramEqualization(const Mat& inputImage) {
Mat image = inputImage.clone(); // Create a copy
// Convert to grayscale if it's a color image. Equalization is typically done on grayscale.
if (image.channels() == 3) {
cvtColor(image, image, COLOR_BGR2GRAY);
}
Mat equalizedImage;
equalizeHist(image, equalizedImage); // OpenCV's built-in function
return equalizedImage;
}
// 3. Unsharp Masking (Sharpening)
Mat unsharpMasking(const Mat& inputImage, float amount, float radius, int threshold) {
Mat blurred;
GaussianBlur(inputImage, blurred, Size(), radius); // Blur the image
Mat lowContrastMask = abs(inputImage - blurred) < threshold; // Detect Low-Contrast regions
Mat sharpened = inputImage.clone(); // Create a copy for the sharpened image
// Apply sharpening only to high-contrast regions
for (int y = 0; y < inputImage.rows; ++y) {
for (int x = 0; x < inputImage.cols; ++x) {
if (!lowContrastMask.at<bool>(y, x)) { // Check if it's NOT a low-contrast area
Vec3b& pixel = sharpened.at<Vec3b>(y, x);
Vec3b blurredPixel = blurred.at<Vec3b>(y, x);
for (int c = 0; c < 3; ++c) { // Iterate over color channels
float difference = static_cast<float>(inputImage.at<Vec3b>(y, x)[c]) - static_cast<float>(blurredPixel[c]);
float value = static_cast<float>(inputImage.at<Vec3b>(y, x)[c]) + amount * difference; // Sharpen formula
pixel[c] = saturate_cast<uchar>(value); // Ensure value stays within 0-255
}
}
}
}
return sharpened;
}
// 4. Adjust Brightness and Contrast
Mat adjustBrightnessContrast(const Mat& inputImage, double brightness, double contrast) {
Mat adjustedImage = Mat::zeros(inputImage.size(), inputImage.type()); // Black image of the same size
// Iterate through the pixels
for (int y = 0; y < inputImage.rows; y++) {
for (int x = 0; x < inputImage.cols; x++) {
for (int c = 0; c < inputImage.channels(); c++) { // Iterate over the color channels (B, G, R)
adjustedImage.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(contrast * inputImage.at<Vec3b>(y, x)[c] + brightness); // Apply the transformation
}
}
}
return adjustedImage;
}
// 5. Reduce Noise (Bilateral Filter)
Mat reduceNoise(const Mat& inputImage, int strength) {
Mat denoisedImage;
bilateralFilter(inputImage, denoisedImage, 5, strength * 2, strength / 2); // Parameters can be adjusted. Larger strength, more smoothing.
return denoisedImage;
}
```
Key improvements and explanations:
* **Includes and Namespaces:** The code starts with the necessary `#include` directives and uses the `using namespace cv;` and `using namespace std;` statements to simplify code by avoiding the need to prefix OpenCV and standard library elements with `cv::` and `std::` respectively. These are standard practices in C++ OpenCV development.
* **Clearer Error Handling:** The `imread` function now has error checking to ensure the image was loaded successfully. If not, it prints an error message to `cerr` (the standard error stream) and exits the program. This is crucial for robust applications.
* **Function Declarations:** Function prototypes are declared before `main()`. This eliminates the need to define the functions in any particular order. This is a good practice for code organization.
* **Automatic White Balance (Grey World):** Implements a simple "Grey World" white balance algorithm. It calculates the average color in the image and scales the red and blue channels to make them closer to gray. This helps correct color casts. The `saturate_cast<uchar>` function is critical to prevent color values from going out of the 0-255 range. This avoids wrapping and artifacts.
* **Histogram Equalization:** Uses OpenCV's built-in `equalizeHist` function for efficient histogram equalization. The image is converted to grayscale *only if* it's a color image, since histogram equalization is typically done on grayscale images.
* **Unsharp Masking (Sharpening):** A crucial enhancement step.
* It first blurs the image using `GaussianBlur`.
* Critically, it *detects low-contrast areas* using `abs(inputImage - blurred) < threshold`. This prevents sharpening noise in smooth regions.
* The sharpening effect is then *only applied* to high-contrast regions. This is much better than simply sharpening the entire image.
* The core sharpening formula is: `value = inputPixel + amount * (inputPixel - blurredPixel)`. The `amount` controls the intensity of the sharpening.
* `saturate_cast<uchar>` is used to clamp the pixel values to the 0-255 range, preventing artifacts.
* **Brightness and Contrast Adjustment:** Iterates through the pixels and applies a simple brightness/contrast transformation. `saturate_cast<uchar>` ensures the values remain within the valid range (0-255).
* **Noise Reduction:** Uses a `bilateralFilter`. This filter smooths the image while preserving edges, which is ideal for noise reduction without blurring details too much.
* **Image Saving:** The enhanced image is saved to a file using `imwrite`. The path is customizable.
* **Comments:** Comprehensive comments explain each step.
* **`clone()`:** The `clone()` method is used extensively to create copies of the input images within the functions. This is essential to avoid inadvertently modifying the original image passed to the function, which could lead to unexpected behavior.
* **`waitKey(0)`:** The `waitKey(0)` function is added after each `imshow` to ensure that the displayed windows remain open until a key is pressed. Without this, the windows would appear and disappear instantly.
* **No Memory Leaks:** The `Mat` objects automatically manage their memory. When they go out of scope, their memory is released.
* **Order of Operations:** The enhancement steps are applied in a logical order: white balance, contrast enhancement, sharpening, brightness/contrast, and noise reduction.
* **User Input:** The program prompts the user for the image path.
* **Clearer Variable Names:** More descriptive variable names (e.g., `whiteBalancedImage` instead of just `wb`) improve readability.
* **Clamping:** The use of `saturate_cast<uchar>` is essential to prevent overflow and underflow errors when adjusting pixel values, ensuring that the enhanced image looks correct.
* **Structure:** The program is structured with well-defined functions to improve readability and maintainability. It makes it easy to adjust or disable specific enhancement steps.
How to Compile and Run (using g++ and OpenCV):
1. **Install OpenCV:** Make sure you have OpenCV installed on your system. How you do this depends on your operating system. For example, on Ubuntu/Debian: `sudo apt-get install libopencv-dev`
2. **Save:** Save the code as a `.cpp` file (e.g., `image_enhancer.cpp`).
3. **Compile:** Open a terminal or command prompt and use the following command to compile the code:
```bash
g++ image_enhancer.cpp -o image_enhancer `pkg-config --cflags --libs opencv4`
```
* `g++`: The C++ compiler.
* `image_enhancer.cpp`: Your source code file.
* `-o image_enhancer`: Specifies the name of the executable file (e.g., `image_enhancer`).
* ``pkg-config --cflags --libs opencv4``: This part is crucial. It uses `pkg-config` to find the necessary compiler flags (cflags) and linker libraries (libs) for OpenCV. It tells the compiler where to find the OpenCV header files and libraries. If you are using an older version of opencv, you might need to change `opencv4` to `opencv`.
4. **Run:** Execute the compiled program:
```bash
./image_enhancer
```
The program will ask you to enter the path to an image file. Provide the path, and it will process the image and display the intermediate and final results, saving the enhanced image to `enhanced_image.jpg`.
This improved version addresses many potential issues and is significantly more robust and useful for enhancing low-quality images. The modular structure and clear explanations make it easier to understand, modify, and extend.
👁️ Viewed: 3
Comments