Соответствие цветов OpenCV

#python #c #opencv

Вопрос:

Я пытаюсь следовать функции python отсюда, чтобы применить сопоставление цветов в OpenCV. Это функция python (без опции маски):

 #!/usr/bin/env python
import cv2 # Import the OpenCV library
import numpy as np # Import Numpy library
import matplotlib.pyplot as plt # Import matplotlib functionality
import sys # Enables the passing of arguments
# Define the file name of the images
SOURCE_IMAGE = "aspens_in_fall.jpg"
REFERENCE_IMAGE = "forest_resized.jpg"
MASK_IMAGE = "mask.jpg"
OUTPUT_IMAGE = "aspens_in_fall_forest_output"
OUTPUT_MASKED_IMAGE = "aspens_in_fall_forest_output_masked.jpg"
 
def calculate_cdf(histogram):
    """
    This method calculates the cumulative distribution function
    :param array histogram: The values of the histogram
    :return: normalized_cdf: The normalized cumulative distribution function
    :rtype: array
    """
    # Get the cumulative sum of the elements
    cdf = histogram.cumsum()
 
    # Normalize the cdf
    normalized_cdf = cdf / float(cdf.max())
 
    return normalized_cdf
 
def calculate_lookup(src_cdf, ref_cdf):
    """
    This method creates the lookup table
    :param array src_cdf: The cdf for the source image
    :param array ref_cdf: The cdf for the reference image
    :return: lookup_table: The lookup table
    :rtype: array
    """
    lookup_table = np.zeros(256)
    lookup_val = 0
    for src_pixel_val in range(len(src_cdf)):
        lookup_val
        for ref_pixel_val in range(len(ref_cdf)):
            if ref_cdf[ref_pixel_val] >= src_cdf[src_pixel_val]:
                lookup_val = ref_pixel_val
                break
        lookup_table[src_pixel_val] = lookup_val
    return lookup_table
 
def match_histograms(src_image, ref_image):
    """
    This method matches the source image histogram to the
    reference signal
    :param image src_image: The original source image
    :param image  ref_image: The reference image
    :return: image_after_matching
    :rtype: image (array)
    """
    # Split the images into the different color channels
    # b means blue, g means green and r means red
    src_b, src_g, src_r = cv2.split(src_image)
    ref_b, ref_g, ref_r = cv2.split(ref_image)
 
    # Compute the b, g, and r histograms separately
    # The flatten() Numpy method returns a copy of the array c
    # collapsed into one dimension.
    src_hist_blue, bin_0 = np.histogram(src_b.flatten(), 256, [0,256])
    src_hist_green, bin_1 = np.histogram(src_g.flatten(), 256, [0,256])
    src_hist_red, bin_2 = np.histogram(src_r.flatten(), 256, [0,256])    
    ref_hist_blue, bin_3 = np.histogram(ref_b.flatten(), 256, [0,256])    
    ref_hist_green, bin_4 = np.histogram(ref_g.flatten(), 256, [0,256])
    ref_hist_red, bin_5 = np.histogram(ref_r.flatten(), 256, [0,256])
 
    # Compute the normalized cdf for the source and reference image
    src_cdf_blue = calculate_cdf(src_hist_blue)
    src_cdf_green = calculate_cdf(src_hist_green)
    src_cdf_red = calculate_cdf(src_hist_red)
    ref_cdf_blue = calculate_cdf(ref_hist_blue)
    ref_cdf_green = calculate_cdf(ref_hist_green)
    ref_cdf_red = calculate_cdf(ref_hist_red)
 
    # Make a separate lookup table for each color
    blue_lookup_table = calculate_lookup(src_cdf_blue, ref_cdf_blue)
    green_lookup_table = calculate_lookup(src_cdf_green, ref_cdf_green)
    red_lookup_table = calculate_lookup(src_cdf_red, ref_cdf_red)
 
    # Use the lookup function to transform the colors of the original
    # source image
    blue_after_transform = cv2.LUT(src_b, blue_lookup_table)
    green_after_transform = cv2.LUT(src_g, green_lookup_table)
    red_after_transform = cv2.LUT(src_r, red_lookup_table)
 
    # Put the image back together
    image_after_matching = cv2.merge([
        blue_after_transform, green_after_transform, red_after_transform])
    image_after_matching = cv2.convertScaleAbs(image_after_matching)
 
    return image_after_matching
 
 

И это моя попытка на C :

 Mat Flatten(const Matamp; mat)
{
    auto m2 = mat.reshape(1, 1);
    return m2;
}




Mat calculate_cdf(Mat m) 
{
    cv::Mat accumulatedHist = m.clone();
    for (int i = 1; i < m.rows; i  ) {
        {
            floatamp; f1 = accumulatedHist.at<float>(i);
            f1  = accumulatedHist.at<float>(i - 1);
        }
    }

    float maxx = 0;
    for (int i = 0; i < m.rows; i  ) {
        if (accumulatedHist.at<float>(i) > maxx)
            maxx = accumulatedHist.at<float>(i);
    }
    for (int i = 0; i < m.rows; i  ) {
        accumulatedHist.at<float>(i) /= maxx;
    }
    return accumulatedHist;
    }


   
Mat calculate_lookup(Mat src_cdf, Mat ref_cdf)
{
    Mat lookup_table = Mat::zeros(256, 1, CV_32FC1);
    float lookup_val = 0;
    for (int src_pixel_val = 0; src_pixel_val < src_cdf.rows; src_pixel_val  )
    {
        float lookup_val = 0;
        for (int ref_pixel_val = 0; ref_pixel_val < ref_cdf.rows; ref_pixel_val  )
        {
            if (ref_cdf.data[ref_pixel_val] >= src_cdf.data[src_pixel_val])
            {
                lookup_val = ref_pixel_val;
                break;
            }
        }
        lookup_table.data[src_pixel_val] = lookup_val;
    }
    return lookup_table;
}

Mat hm(Mat src_image, Mat ref_image)
{
    // Split images
    Mat src[3];
    split(src_image,src);
    Mat ref[3];
    split(ref_image, ref);

    // Compute the b, g, and r histograms separately
    float range[] = { 0, 256 };
    const float* histRange = { range };
    bool uniform = 1, accumulate = 0;
    Mat src_hist_blue, src_hist_green, src_hist_red;
    Mat ref_hist_blue, ref_hist_green, ref_hist_red;
    int histSize = 256; // expected
    calcHist(amp;Flatten(src[0]), 1, 0, Mat(), src_hist_blue, 1, amp;histSize, amp;histRange, uniform, accumulate);
    calcHist(amp;Flatten(src[1]), 1, 0, Mat(), src_hist_green, 1, amp;histSize, amp;histRange, uniform, accumulate);
    calcHist(amp;Flatten(src[2]), 1, 0, Mat(), src_hist_red, 1, amp;histSize, amp;histRange, uniform, accumulate);
    
    calcHist(amp;Flatten(ref[0]), 1, 0, Mat(), ref_hist_blue, 1, amp;histSize, amp;histRange, uniform, accumulate);
    calcHist(amp;Flatten(ref[1]), 1, 0, Mat(), ref_hist_green, 1, amp;histSize, amp;histRange, uniform, accumulate);
    calcHist(amp;Flatten(ref[2]), 1, 0, Mat(), ref_hist_red, 1, amp;histSize, amp;histRange, uniform, accumulate);


    auto src_cdf_blue = calculate_cdf(src_hist_blue);
    auto src_cdf_green = calculate_cdf(src_hist_green);
    auto src_cdf_red = calculate_cdf(src_hist_red);
    auto ref_cdf_blue = calculate_cdf(ref_hist_blue);
    auto ref_cdf_green = calculate_cdf(ref_hist_green);
    auto ref_cdf_red = calculate_cdf(ref_hist_red);

    auto blue_lookup_table = calculate_lookup(src_cdf_blue, ref_cdf_blue);
    auto green_lookup_table = calculate_lookup(src_cdf_green, ref_cdf_green);
    auto red_lookup_table = calculate_lookup(src_cdf_red, ref_cdf_red);

    Mat at[3];
    auto to = src[0].total();
    to = blue_lookup_table.total();
    to = blue_lookup_table.channels();
    LUT(src[0], blue_lookup_table,at[2]);
    LUT(src[1], green_lookup_table, at[1]);
    LUT(src[2], red_lookup_table, at[0]);


    Mat image_after_matching;
    merge(at, 3, image_after_matching);
    Mat dst;
    convertScaleAbs(image_after_matching, dst);
    return dst;
}

int main()
{
    Mat image_src = imread("r:\15.jpg");
    Mat image_ref = imread("r:\130.jpg");

    Mat i3 = hm(image_src, image_ref);
    DeleteFile(L"r:\r.jpg");
    imwrite("r:\r.jpg", i3);
    ShellExecute(0, L"open", L"r:\r.jpg", 0, 0, 0);
}
 

Первое Изображение
Второе Изображение

И это мой результат:

Результат

Если accumulate параметр равен true, то результаты будут в равной степени неверными. Я не уверен, правильно ли я преобразовал код Python, поэтому буду признателен за любую помощь.

Комментарии:

1.(1) вы не можете просто at<float> использовать коврик, которого нет CV_32F . типы должны совпадать, иначе вы получите доступ к мусору. вам нужно создать новый коврик с правильным типом, а затем поработать с ним. доступ к входу как at<uint8_t> , выходу как at<float> . (2) calculate_cdf нуждается в нормализации, которая отсутствует в переводе C . — Я не знаю, есть ли еще какие-то проблемы. отсюда просто комментарий. если этот совет решит проблему, пожалуйста, дайте мне знать, чтобы я мог превратить это в ответ.

2. @ChristophRackwitz разве src_hist_blue уже не CF_32F ? ( Я отредактировал cdf и функции поиска).

3. Я так не думаю. calcHist возвращает что-то, что содержит количество , и это целое число. вы можете проверить тип объекта Mat. несмотря на это, разделения по-прежнему не было, так что шкала значений тоже была отключена.