//
//bool isRed(Vec3b color) {
//    // Define the lower and upper bounds for red color
//    Scalar lower_red = Scalar(0, 0, 100); // Adjust as needed
//    Scalar upper_red = Scalar(80, 80, 255); // Adjust as needed
//
//    // Convert the input color to a scalar for comparison
//    Scalar target_color = Scalar(color[0], color[1], color[2]);
//
//    // Check if the input color is within the specified range of red
//    return (target_color.val[0] >= lower_red.val[0] && target_color.val[0] <= upper_red.val[0] &&
//        target_color.val[1] >= lower_red.val[1] && target_color.val[1] <= upper_red.val[1] &&
//        target_color.val[2] >= lower_red.val[2] && target_color.val[2] <= upper_red.val[2]);
//}
//
//int DominantColour() {
//    // Read the input image
//    //cv::Mat image = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\redcar.jpg");
//    cv::Mat image = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\Bluecar.jpeg");
//
//    if (image.empty()) {
//        std::cout << "Could not open or find the image" << std::endl;
//        return -1;
//    }
//
//    // Reshape the image into a 2D array of pixels
//    Mat pixels = image.reshape(1, image.rows * image.cols);
//
//    // Convert pixel values to floats
//    pixels.convertTo(pixels, CV_32F);
//
//    // Define the number of clusters (colors) to find
//    int numClusters = 3; // Adjust as needed
//
//    // Perform K-means clustering
//    Mat labels, centers;
//    kmeans(pixels, numClusters, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0), 3, KMEANS_PP_CENTERS, centers);
//
//    // Find the dominant colors
//    vector<Vec3b> dominantColors;
//    for (int i = 0; i < numClusters; ++i) {
//        Vec3b color;
//        color[0] = centers.at<float>(i, 0); // Blue
//        color[1] = centers.at<float>(i, 1); // Green
//        color[2] = centers.at<float>(i, 2); // Red
//        dominantColors.push_back(color);
//    }
//
//    // Print the dominant colors
//    cout << "Dominant colors:" << endl;
//    for (int i = 0; i < numClusters; ++i) {
//        cout << "Color " << i + 1 << ": BGR(" << (int)dominantColors[i][0] << ", " << (int)dominantColors[i][1] << ", " << (int)dominantColors[i][2] << ")" << endl;
//    }
//
//    // Display the dominant colors
//    Mat colorPalette(100, 100 * numClusters, CV_8UC3);
//    for (int i = 0; i < numClusters; ++i) {
//        rectangle(colorPalette, Point(i * 100, 0), Point((i + 1) * 100, 100), Scalar(dominantColors[i]), -1); // Filled rectangle
//    }
//    imshow("Dominant Colors", colorPalette);
//
//    // Wait for key press to exit
//    waitKey(0);
//
//    return 0;
//}
//// Function to determine basic color from 8 basic colors based on BGR values
//string getBasicColor(Vec3b color) {
//    // Define 8 basic colors and their BGR values
//    map<string, Vec3b> basicColors = {
//        {"Red", {0, 0, 255}},
//        {"Green", {0, 255, 0}},
//        {"Blue", {255, 0, 0}},
//        {"Yellow", {0, 255, 255}},
//        {"Black", {0, 0, 0}},
//        {"White", {255, 255, 255}},
//        {"Brown", {42, 42, 165}},
//        {"Gray", {128, 128, 128}}
//    };
//
//    string basicColor = "Other";
//
//    // Find the basic color closest to the given color
//    int minDistance = INT_MAX;
//    for (const auto& entry : basicColors) {
//        int dist = norm(entry.second, color, NORM_L2SQR);
//        if (dist < minDistance) {
//            minDistance = dist;
//            basicColor = entry.first;
//        }
//    }
//
//    return basicColor;
//}
//
//int GetColour() {
//    // Read the image
//    Mat image = imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\redcar.jpg");
//    if (image.empty()) {
//        cerr << "Error: Unable to read image." << endl;
//        return -1;
//    }
//
//    // Initialize variables to count occurrences of 8 basic colors
//    map<string, int> colorCounts;
//    for (const auto& entry : {
//        "Red", "Green", "Blue", "Yellow", "Black", "White", "Brown", "Gray"
//        }) {
//        colorCounts[entry] = 0;
//    }
//
//    // Iterate over image pixels to count occurrences of 8 basic colors
//    for (int i = 0; i < image.rows; ++i) {
//        for (int j = 0; j < image.cols; ++j) {
//            Vec3b pixelColor = image.at<Vec3b>(i, j);
//            string basicColor = getBasicColor(pixelColor);
//            colorCounts[basicColor]++;
//        }
//    }
//
//    // Find the dominant basic color
//    string dominantBasicColor = "Other";
//    int maxCount = 0;
//    for (const auto& entry : colorCounts) {
//        if (entry.second > maxCount) {
//            maxCount = entry.second;
//            dominantBasicColor = entry.first;
//        }
//    }
//
//    // Get the BGR color code of the dominant basic color
//    Vec3b dominantBGRColor;
//    if (dominantBasicColor == "Red")
//        dominantBGRColor = Vec3b(0, 0, 255);
//    else if (dominantBasicColor == "Green")
//        dominantBGRColor = Vec3b(0, 255, 0);
//    else if (dominantBasicColor == "Blue")
//        dominantBGRColor = Vec3b(255, 0, 0);
//    else if (dominantBasicColor == "Yellow")
//        dominantBGRColor = Vec3b(0, 255, 255);
//    else if (dominantBasicColor == "Black")
//        dominantBGRColor = Vec3b(0, 0, 0);
//    else if (dominantBasicColor == "White")
//        dominantBGRColor = Vec3b(255, 255, 255);
//    else if (dominantBasicColor == "Brown")
//        dominantBGRColor = Vec3b(42, 42, 165);
//    else if (dominantBasicColor == "Gray")
//        dominantBGRColor = Vec3b(128, 128, 128);
//
//    // Create a new image with the dominant color filled
//    Mat dominantColorImage(image.size(), CV_8UC3, dominantBGRColor);
//
//    // Display the dominant color in a separate window
//    namedWindow("Dominant Color", WINDOW_AUTOSIZE);
//    imshow("Dominant Color", dominantColorImage);
//    waitKey(0);
//
//    return 0;
//}
//
//int DetectRedCar() {
//    // Read the input image
//    cv::Mat image = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\Bluecar.jpeg");
//
//    if (image.empty()) {
//        cout << "Could not open or find the image" << endl;
//        return -1;
//    }
//
//    // Reshape the image into a 2D array of pixels
//    Mat pixels = image.reshape(1, image.rows * image.cols);
//
//    // Convert pixel values to floats
//    pixels.convertTo(pixels, CV_32F);
//
//    // Define the number of clusters (colors) to find
//    int numClusters = 3; // Adjust as needed
//
//    // Perform K-means clustering
//    Mat labels, centers;
//    kmeans(pixels, numClusters, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0), 3, KMEANS_PP_CENTERS, centers);
//
//    // Find the dominant colors
//    vector<Vec3b> dominantColors;
//    for (int i = 0; i < numClusters; ++i) {
//        Vec3b color;
//        color[0] = centers.at<float>(i, 0); // Blue
//        color[1] = centers.at<float>(i, 1); // Green
//        color[2] = centers.at<float>(i, 2); // Red
//        dominantColors.push_back(color);
//    }
//
//    // Check if any of the dominant colors are red
//    bool redDetected = false;
//    for (int i = 0; i < numClusters; ++i) {
//        if (isRed(dominantColors[i])) {
//            redDetected = true;
//            break;
//        }
//    }
//
//    // Print the result
//    if (redDetected) {
//        cout << "A red car is detected in the image." << endl;
//    }
//    else {
//        cout << "No red car is detected in the image." << endl;
//    }
//
//    return 0;
//}
//
//double CalculateIoU(const cv::Rect& box1, const cv::Rect& box2) {
//    int x1 = std::max(box1.x, box2.x);
//    int y1 = std::max(box1.y, box2.y);
//    int x2 = std::min(box1.x + box1.width, box2.x + box2.width);
//    int y2 = std::min(box1.y + box1.height, box2.y + box2.height);
//
//    int intersectionArea = std::max(0, x2 - x1) * std::max(0, y2 - y1);
//    int box1Area = box1.width * box1.height;
//    int box2Area = box2.width * box2.height;
//
//    double iou = static_cast<double>(intersectionArea) / (box1Area + box2Area - intersectionArea);
//    return iou;
//}
//void NonMaximumSuppression(std::vector<DetectionObject>& detectedObjects, double iouThreshold) {
//    std::sort(detectedObjects.begin(), detectedObjects.end(),
//        [](const DetectionObject& a, const DetectionObject& b) {
//            return a.confidence > b.confidence;
//        });
//
//    std::vector<DetectionObject> finalDetections;
//    while (!detectedObjects.empty()) {
//        finalDetections.push_back(detectedObjects.front());
//        detectedObjects.erase(detectedObjects.begin());
//
//        for (auto it = detectedObjects.begin(); it != detectedObjects.end(); ) {
//            if (CalculateIoU(finalDetections.back().box, it->box) > iouThreshold) {
//                it = detectedObjects.erase(it);
//            }
//            else {
//                ++it;
//            }
//        }
//    }
//
//    detectedObjects = std::move(finalDetections);
//}
//std::vector<DetectionObject> findMatches(cv::Mat& img, cv::Mat& templ, double threshold) {
//    // Create the result matrix
//    std::vector<DetectionObject> detectedObjects;
//    int result_cols = img.cols - templ.cols + 1;
//    int result_rows = img.rows - templ.rows + 1;
//    cv::Mat result(result_rows, result_cols, CV_32FC1);
//
//    // Perform match
//    cv::matchTemplate(img, templ, result, cv::TM_CCOEFF_NORMED);
//    cv::normalize(result, result, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
//
//    std::vector<cv::Rect> boundingBoxes;
//
//    // Threshold and find non-zero locations
//    for (int i = 0; i < result.rows; i++) {
//        for (int j = 0; j < result.cols; j++) {
//            if (result.at<float>(i, j) > threshold) {
//                cv::Rect rect(j, i, templ.cols, templ.rows);
//                DetectionObject object;
//                object.box = rect;
//                boundingBoxes.push_back(rect);
//                detectedObjects.push_back(object);
//                // Optional: Draw rectangles on the image
//                cv::rectangle(img, rect, cv::Scalar(0, 0, 255), 2);
//            }
//        }
//    }
//    NonMaximumSuppression(detectedObjects, 0.5);
//    std::cout << "Bounding box size:" << boundingBoxes.size()<<std::endl;
//    std::cout << "detectedObjects box size:" << detectedObjects.size() << std::endl;
//
//    return detectedObjects;
//}
//
//int PatternMatching() {
//    // Load the image and the template
//    cv::Mat img = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\QR\\QRSample.jpg", cv::IMREAD_COLOR);
//    cv::Mat templ = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\QR\\Ultracode.jpg", cv::IMREAD_COLOR);
//
//    if (img.empty() || templ.empty()) {
//        std::cout << "Could not open or find the image or template" << std::endl;
//        return -1;
//    }
//
//    // Call findMatches with a threshold, e.g., 0.8 for 80% similarity
//    std::vector<DetectionObject> matches = findMatches(img, templ, 0.8);
//
//    // Display the image with drawn rectangles
//    cv::imshow("Matches", img);
//    cv::waitKey(0);
//
//
//    return 0;
//}

//int TestZingQRcode() {
//
//    // load your image data from somewhere. ImageFormat::Lum assumes grey scale image data
//
//    cv::Mat inputImage = cv::imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\QR\\Code128.jpg");
//    cv::Mat grayMat;
//    if (inputImage.channels() == 3) {
//        cv::cvtColor(inputImage, grayMat, cv::COLOR_BGR2GRAY);
//    }
//    else if (inputImage.channels() == 4) {
//        cv::cvtColor(inputImage, grayMat, cv::COLOR_BGRA2GRAY);
//    }
//    else {
//        grayMat = inputImage; // Already grayscale
//    }
//    
//    int width = grayMat.cols;
//    int height= grayMat.rows;
//    unsigned char* data = grayMat.data;
//    auto image = ZXing::ImageView(data, width, height, ZXing::ImageFormat::Lum);
//    auto options = ZXing::ReaderOptions().setFormats(ZXing::BarcodeFormat::Any);
//    auto barcodes = ZXing::ReadBarcodes(image, options);
//    if (barcodes.size() > 0) {
//        for (const auto& b : barcodes) {
//            std::cout << ZXing::ToString(b.format()) << ": " << b.text() << "\n";
//            ZXing::Position pos =b.position();
//            std::cout<<"Pos 1:("<<pos[0].x<<","<< pos[0].x<<")"<<std::endl;
//        }
//            
//    }
//    else {
//        std::cout << "Could not find any barcode"<<std::endl;
//    }
//
//    return 0;
//}
//
//
//
//Vec3f estimateIllumination(Mat& src, float percentile) {
//    Mat src_float;
//    src.convertTo(src_float, CV_32FC3);
//    vector<Mat> channels(3);
//    split(src_float, channels);
//
//    Mat magnitude = Mat::zeros(src.size(), CV_32FC1);
//
//    for (int i = 0; i < 3; i++) {
//        Mat sobelx, sobely;
//        Sobel(channels[i], sobelx, CV_32F, 1, 0);
//        Sobel(channels[i], sobely, CV_32F, 0, 1);
//        magnitude += sobelx.mul(sobelx) + sobely.mul(sobely);
//    }
//
//    sqrt(magnitude, magnitude);
//    Mat flatMagnitude = magnitude.reshape(1, 1);
//    cv::sort(flatMagnitude, flatMagnitude, SORT_EVERY_ROW + SORT_DESCENDING);
//    int thresholdIdx = static_cast<int>(percentile * flatMagnitude.total() / 100.0);
//    double threshold = flatMagnitude.at<float>(thresholdIdx);
//
//    Mat mask = magnitude >= threshold;
//    Scalar meanVal = mean(src_float, mask);
//
//    cout << "Estimated illumination: " << meanVal << endl;
//    return Vec3f(meanVal[0], meanVal[1], meanVal[2]);
//}
//
//void applyWhiteBalance(Mat& src, Mat& dst, Vec3f illumination) {
//    vector<Mat> channels(3);
//    src.convertTo(src, CV_32FC3);
//    split(src, channels);
//
//    for (int i = 0; i < 3; i++) {
//        channels[i] /= illumination[i];
//    }
//
//    merge(channels, dst);
//    dst.convertTo(dst, CV_8U);
//}
//
//void simpleWhiteBalance(Mat& src, Mat& dst) {
//    // Convert image to floating point for precision
//    src.convertTo(dst, CV_32F);
//
//    // Split the image into separate color channels
//    vector<Mat> channels(3);
//    split(dst, channels);
//
//    // Calculate the average intensity for each channel
//    double avgB = mean(channels[0])[0];
//    double avgG = mean(channels[1])[0];
//    double avgR = mean(channels[2])[0];
//
//    // Calculate the total average intensity
//    double avgTotal = (avgB + avgG + avgR) / 3.0;
//
//    // Scale each channel to adjust the white balance
//    channels[0] *= avgTotal / avgB;
//    channels[1] *= avgTotal / avgG;
//    channels[2] *= avgTotal / avgR;
//
//    // Merge the channels back into one image
//    merge(channels, dst);
//
//    // Convert back to 8-bit color
//    dst.convertTo(dst, CV_8U);
//}
//int AutoWhiteBalance() {
//    Mat src = imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\cat.jpg");
//    if (src.empty()) {
//        cout << "Could not open or find the image" << endl;
//        return -1;
//    }
//
//    Mat dst;
//    Vec3f illumination = estimateIllumination(src, 0.1); // Top 1% of gradients
//    applyWhiteBalance(src, dst, illumination);
//
//    //simpleWhiteBalance(src,dst);
//    imshow("Original Image", src);
//    imshow("White Balanced Image", dst);
//    cv::waitKey(0);
//
//    return 0;
//}
//
//
//int BrightEnhancement() {
//    // Load the input image
//    Mat inputImage = imread("C:\\Projects\\ANSVIS\\Documentation\\TestImages\\ANSCVAImages\\dark.jpg", IMREAD_COLOR);
//
//    // Check if the image was loaded successfully
//    if (inputImage.empty()) {
//        cout << "Error: Could not open or find the image" << endl;
//        return -1;
//    }
//
//    // Separate the input image into B, G, and R channels
//    vector<Mat> channels;
//    split(inputImage, channels);
//
//    // Enhance brightness for each channel individually
//    double brightnessScaleFactor = 1.5; // Scaling factor for brightness enhancement
//    for (int i = 0; i < channels.size(); ++i) {
//        channels[i] *= brightnessScaleFactor;
//    }
//
//    // Merge the channels back into a BGR image
//    Mat enhancedImage;
//    merge(channels, enhancedImage);
//
//    // Display original and enhanced images
//    namedWindow("Original Image", WINDOW_AUTOSIZE);
//    imshow("Original Image", inputImage);
//
//    namedWindow("Enhanced Image", WINDOW_AUTOSIZE);
//    imshow("Enhanced Image", enhancedImage);
//
//    // Wait for a keystroke in the window
//    waitKey(0);
//
//    // Close all OpenCV windows
//    destroyAllWindows();
//
//    return 0;
//}