Problem: Gaussian-weighted Image Metrics

The problem involves locating a binary file (AA), reading specified 600x600 bands (flipping rows vertically), stretching pixel values, and computing Gaussian-weighted statistics (sum, mean, variance, correlation, entropy) for tasks like summation, statistical analysis, and feature extraction, with error handling for missing files.


Input/Output: The problem receives integer band indices (e.g., band_r, band_g, band_b for 9.1; band_num for 9.2; band1–band3 for 9.3/9.5) and double parameters (stretch_factor for 9.1/9.2/9.4/9.6; weights w1–w3 for 9.3). It locates a binary file "AA" in paths "test_data/AA", "../test_data/AA", "../../test_data/AA". For each subproblem, it reads specified 600×600 unsigned char bands, flips rows vertically, and applies operations: stretching values (clamped at 255) for 9.1/9.2/9.4/9.6, Gaussian weighting (sigma = max(rows, cols)/4) for statistical calculations. It returns: 9.1 a long long sum of modified R+G+B; 9.2 a double Gaussian-weighted mean; 9.3 a double square root of Gaussian-weighted variance of weighted band sums; 9.4 an int rounded max-min difference of Gaussian-weighted stretched grayscale; 9.5 a double Gaussian-weighted correlation coefficient; 9.6 a double sum of sqrt(variance) and entropy of Gaussian-weighted grayscale. If the file is missing, it returns -1/-1.0 and outputs an error.

Required dependencies:
#include <vector>
#include <string>
#include <fstream>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
using namespace std;

Sub-steps:
step_number: 1
step_description_prompt: Please write a C++ function named problem_9_1 that takes four parameters (int band_r, int band_g, int band_b, double stretch_factor) and returns a long long. This function reads a binary file to extract R, G, B band data, applies a stretch factor to each band value, and computes the sum of the stretched values.
Function definition: long long problem_9_1(int band_r, int band_g, int band_b, double stretch_factor);
Algorithm steps: 1. Check three possible paths ("test_data/AA", "../test_data/AA", "../../test_data/AA") to find the existing binary file. If no file is found, output "Error: Cannot find data file AA" to cerr and return -1. 2. Initialize three 600x600 (rows=600, cols=600) vector<vector<unsigned char>> bandR, bandG, bandB with 0. 3. Open the file in binary mode. Use a unsigned char buffer of size cols. For each band (b=0 for R, b=1 for G, b=2 for B): a. Compute skip = (b==0 ? band_r-1 : (b==1 ? band_g-1 : band_b-1)) * rows * cols. b. Use file.seekg(skip, ios::beg). c. For i from 0 to rows-1: read cols bytes into buffer, then assign buffer[j] to bandX[rows-1 - i][j] (X is R/G/B based on b). 4. For each pixel (i,j), compute r = min(255, (int)(bandR[i][j] * stretch_factor)), g = min(255, (int)(bandG[i][j] * stretch_factor)), b = min(255, (int)(bandB[i][j] * stretch_factor)). Sum r+g+b for all pixels and return the total.
Note: The function uses binary file reading. Assume all included headers (like <fstream>, <vector>, <algorithm>) and functions are predefined.
function_header: long problem_9_1(int band_r, int band_g, int band_b, double stretch_factor)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 9.1" << endl;
    
    int correct_count = 0;
    
    // Test 1
    int band_r1 = 1;
    int band_g1 = 2;
    int band_b1 = 3;
    double stretch1 = 1.5;
    long long result1 = problem_9_1(band_r1, band_g1, band_b1, stretch1);    long long correct1 = 88325295LL;  // Expected value (updated from actual result)
    if (result1 == correct1) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
    }

    // Test 2
    int band_r2 = 2;
    int band_g2 = 3;
    int band_b2 = 4;
    double stretch2 = 2.0;
    long long result2 = problem_9_1(band_r2, band_g2, band_b2, stretch2);    long long correct2 = 93088357LL;  // Expected value (updated from actual result)
    if (result2 == correct2) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
    }

    // Test 3
    int band_r3 = 3;
    int band_g3 = 4;
    int band_b3 = 5;
    double stretch3 = 2.5;
    long long result3 = problem_9_1(band_r3, band_g3, band_b3, stretch3);    long long correct3 = 133645576LL;  // Expected value (updated from actual result)
    if (result3 == correct3) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
    }
    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 2
step_description_prompt: Please write a C++ function named problem_9_2 that takes an int band_num and a double stretch_factor, returns a double, which computes the Gaussian-weighted mean of a specific band from a binary file after stretching pixel values.
The function is defined as double problem_9_2(int band_num, double stretch_factor).
First, check three file paths ("test_data/AA", "../test_data/AA", "../../test_data/AA") to find the existing binary file; if none found, output "Error: Cannot find data file AA" to cerr and return -1.0. Then, read the specified band (band_num) from the file: open in binary mode, skip (band_num-1)*600*600 bytes from the start, read each row into a buffer, and store in a 2D vector<vector<unsigned char>> band (600 rows, 600 cols) by flipping rows vertically (use band[rows-1-i][j] for each row i). Next, for each pixel (i,j), stretch the value to min(255.0, band[i][j]*stretch_factor), calculate Gaussian weight using sigma = max(rows, cols)/4.0 (center at (rows/2.0, cols/2.0)) and distance squared from center, sum the weighted stretched values and weights. Finally, return the ratio of weighted_sum to weight_sum (or 0.0 if weight_sum ≤ 1e-10).
Ensure correct binary file handling, band selection, row flipping, value stretching, and Gaussian-weighted average calculation.
function_header: double problem_9_2(int band_num, double stretch_factor)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 9.2" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    int band1 = 1;
    double stretch1 = 1.5;

    double result1 = problem_9_2(band1, stretch1);
    if (result1 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct1 = 122.399828;  // Expected value (updated from actual result)
        if (abs(result1 - correct1) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 2
    int band2 = 2;
    double stretch2 = 2.0;

    double result2 = problem_9_2(band2, stretch2);
    if (result2 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct2 = 74.779031;  // Expected value (updated from actual result)
        if (abs(result2 - correct2) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 3
    int band3 = 3;
    double stretch3 = 2.5;

    double result3 = problem_9_2(band3, stretch3);
    if (result3 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct3 = 106.831320;  // Expected value (updated from actual result)
        if (abs(result3 - correct3) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }

    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 3
step_description_prompt: Please use C++ code to create a function named problem_9_3 that calculates the Gaussian-weighted standard deviation of the weighted combination of three specified bands from a binary data file. The function is defined as double problem_9_3(int band1, int band2, int band3, double w1, double w2, double w3). 

Algorithm flow: 
1. Search for the binary file "AA" in paths {"test_data/AA", "../test_data/AA", "../../test_data/AA"}. If not found, output "Error: Cannot find data file AA" to cerr and return -1.0. 
2. For each band (band1, band2, band3), read 600x600 unsigned char pixels from the found file: skip (bandX - 1)*600*600 bytes from the start, read each row (600 bytes) in binary mode, and store rows in reverse order (rows-1 - i for row index i). 
3. Calculate Gaussian weights with center at (300.0, 300.0) and sigma = 150.0 (max(600,600)/4.0). Weight for (i,j) is exp(-( (i-300.0)^2 + (j-300.0)^2 )/(2*150.0*150.0)). 
4. Compute weighted sum of combined values (w1*b1[i][j] + w2*b2[i][j] + w3*b3[i][j]) and sum of weights to get the weighted mean. 
5. Compute weighted variance using (combined_val - mean)^2 * weight, then return the square root of (variance = weighted_variance / weight_sum if weight_sum > 1e-10 else 0.0). 

Note: Use binary mode to read files, skip (bandX-1)*600*600 bytes for each band, and reverse row order when storing pixels. Assume other called functions are pre-defined.
function_header: double problem_9_3(int band1, int band2, int band3, double w1, double w2, double w3)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 9.3" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    int b1_1 = 1, b2_1 = 2, b3_1 = 3;
    double w1_1 = 0.3, w2_1 = 0.4, w3_1 = 0.3;

    double result1 = problem_9_3(b1_1, b2_1, b3_1, w1_1, w2_1, w3_1);
    if (result1 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct1 = 6.786629;  // Expected value (updated from actual result)
        if (abs(result1 - correct1) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 2
    int b1_2 = 2, b2_2 = 3, b3_2 = 4;
    double w1_2 = 0.4, w2_2 = 0.3, w3_2 = 0.3;

    double result2 = problem_9_3(b1_2, b2_2, b3_2, w1_2, w2_2, w3_2);
    if (result2 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct2 = 5.992171;  // Expected value (updated from actual result)
        if (abs(result2 - correct2) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 3
    int b1_3 = 3, b2_3 = 4, b3_3 = 5;
    double w1_3 = 0.5, w2_3 = 0.3, w3_3 = 0.2;

    double result3 = problem_9_3(b1_3, b2_3, b3_3, w1_3, w2_3, w3_3);
    if (result3 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct3 = 8.961730;  // Updated with actual result
        if (abs(result3 - correct3) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }

    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 4
step_description_prompt: Please use C++ code to generate a function named problem_9_4 that reads three bands of binary data from a file, performs Gaussian-weighted range calculation, and returns the integer difference between the maximum and minimum grayscale values after processing.
The function is defined as int problem_9_4(int band_r, int band_g, int band_b, double stretch_factor).
Algorithm flow: 1. Search for the binary file "AA" in paths {"test_data/AA", "../test_data/AA", "../../test_data/AA"}. 2. Read the specified bands (band_r, band_g, band_b) from the file into 600x600 vectors bandR, bandG, bandB (reverse rows using rows-1-i). 3. Calculate Gaussian weights for each pixel (center at image center, sigma = max(rows, cols)/4.0). 4. Compute stretched RGB values (clamp to 0-255), convert to grayscale, calculate weighted grayscale, track weighted_max, weighted_min and their weights. 5. Compute max_val = weighted_max / max_weight (if max_weight > 1e-10) and min_val = weighted_min / min_weight (if min_weight > 1e-10). Return the rounded integer of (max_val - min_val + 0.5).
When reading the binary file, each band's data size is 600*600. Skip the offset of previous bands using (band_x - 1)*600*600.
Other functions called in the code are assumed to be defined.
function_header: int problem_9_4(int band_r, int band_g, int band_b, double stretch_factor)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 9.4" << endl;
    
    int correct_count = 0;
    
    // Test 1
    int band_r1 = 1;
    int band_g1 = 2;
    int band_b1 = 3;
    double stretch1 = 1.5;

    int result1 = problem_9_4(band_r1, band_g1, band_b1, stretch1);
    if (result1 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        int correct1 = 97;  // Expected value (updated from actual result)
        if (result1 == correct1) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 2
    int band_r2 = 2;
    int band_g2 = 3;
    int band_b2 = 4;
    double stretch2 = 2.0;

    int result2 = problem_9_4(band_r2, band_g2, band_b2, stretch2);
    if (result2 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        int correct2 = 124;  // Expected value (updated from actual result)
        if (result2 == correct2) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 3
    int band_r3 = 3;
    int band_g3 = 4;
    int band_b3 = 5;
    double stretch3 = 2.5;

    int result3 = problem_9_4(band_r3, band_g3, band_b3, stretch3);
    if (result3 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        int correct3 = 166;  // Expected value (updated from actual result)
        if (result3 == correct3) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }

    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 5
step_description_prompt: Please write a C++ function named problem_9_5 that computes the Gaussian-weighted correlation coefficient between two specified bands from a binary data file. The function takes two integers band1 and band2 as inputs and returns a double.

Algorithm flow:
1. Search for the binary file "AA" in paths {"test_data/AA", "../test_data/AA", "../../test_data/AA"} using ifstream in binary mode. If the file is not found, output "Error: Cannot find data file AA" to cerr and return -1.0.
2. For each input band (band1 and band2), read the 600x600 matrix from the file: skip (band-1)*600*600 bytes to locate the band, read each row into a buffer, then store the row in reverse order (row i of the file becomes row 599-i in the matrix).
3. Compute Gaussian weights for each pixel: center at (300.0, 300.0), sigma = 150.0 (max(600,600)/4). Weight for pixel (i,j) is exp(-((i-300.0)^2 + (j-300.0)^2)/(2*150.0*150.0)).
4. Calculate weighted means for both bands: mean = (sum of (pixel value * weight)) / sum of weights (handle division by zero by returning 0.0 if weight sum is too small).
5. Compute weighted numerator (sum of (b1[i][j]-mean1)*(b2[i][j]-mean2)*weight) and weighted denominators (sum of (b1[i][j]-mean1)^2*weight and sum of (b2[i][j]-mean2)^2*weight).
6. Calculate the correlation coefficient as weighted_numerator / sqrt(weighted_denom1 * weighted_denom2). Return 0.0 if the denominator is too small (to avoid division by zero).

Note: Use ifstream for file operations, binary mode, seekg to skip bytes, read into a dynamically allocated unsigned char buffer, and reverse rows when storing data. Handle all file operations (opening, reading, closing) correctly. Ensure variables like rows=600, cols=600 are fixed. Implement all steps with proper data types (unsigned char for pixel values, double for weights and calculations).
function_header: double problem_9_5(int band1, int band2)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 9.5" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    int b1_1 = 1, b2_1 = 2;

    double result1 = problem_9_5(b1_1, b2_1);
    if (abs(result1 + 1.0) < 1e-6) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct1 = 0.914347;  // Expected value (updated from actual result)
        if (abs(result1 - correct1) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 2
    int b1_2 = 2, b2_2 = 3;

    double result2 = problem_9_5(b1_2, b2_2);
    if (abs(result2 + 1.0) < 1e-6) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct2 = 0.966182;  // Expected value (updated from actual result)
        if (abs(result2 - correct2) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 3
    int b1_3 = 3, b2_3 = 4;

    double result3 = problem_9_5(b1_3, b2_3);
    if (abs(result3 + 1.0) < 1e-6) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct3 =  -0.0153987000;  // Expected value (updated from actual result)
        if (abs(result3 - correct3) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }

    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 6
step_description_prompt: Please write a C++ function named problem_9_6 that takes four parameters (int band_r, int band_g, int band_b, double stretch_factor) and returns a double. This function computes a combined metric of weighted standard deviation and entropy from specific bands of a binary file.
The function signature is: double problem_9_6(int band_r, int band_g, int band_b, double stretch_factor).
Algorithm flow:
1. Check three paths ("test_data/AA", "../test_data/AA", "../../test_data/AA") to locate the binary file "AA". If not found, output "Error: Cannot find data file AA" to cerr and return -1.0.
2. Read 600x600 unsigned char data for each band: skip (band_x-1)*600*600 bytes, read each row into a buffer, then store rows in reverse order (rows-1-i instead of i).
3. Apply stretch_factor to each band value (clamp to 0-255 using min(255, ...)), compute grayscale as (r + g + b)/3.0 for each pixel.
4. Calculate Gaussian weights (center at (300, 300), sigma = 150) for each pixel, build a weighted histogram (256 bins) of grayscale values.
5. Compute entropy from the weighted histogram using log2 (ignore probabilities <1e-10).
6. Compute weighted mean and variance of grayscale values with the same Gaussian weights.
7. Return the sum of the square root of variance and entropy.
Note: Use ios::binary for file reading, reverse row order when storing band data, and manage buffer memory with new/delete.
function_header: double problem_9_6(int band_r, int band_g, int band_b, double stretch_factor)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 9.6" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    int band_r1 = 1;
    int band_g1 = 2;
    int band_b1 = 3;
    double stretch1 = 1.5;

    double result1 = problem_9_6(band_r1, band_g1, band_b1, stretch1);
    if (result1 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct1 = 15.837344;  // Expected value (updated from actual result)
        if (abs(result1 - correct1) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 2
    int band_r2 = 2;
    int band_g2 = 3;
    int band_b2 = 4;
    double stretch2 = 2.0;

    double result2 = problem_9_6(band_r2, band_g2, band_b2, stretch2);
    if (result2 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct2 = 17.902503;  // Expected value (updated from actual result)
        if (abs(result2 - correct2) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 3
    int band_r3 = 3;
    int band_g3 = 4;
    int band_b3 = 5;
    double stretch3 = 2.5;

    double result3 = problem_9_6(band_r3, band_g3, band_b3, stretch3);
    if (result3 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct3 = 33.904678;  // Expected value (updated from actual result)
        if (abs(result3 - correct3) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }

    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

General solution:

General tests: