#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. несмотря на это, разделения по-прежнему не было, так что шкала значений тоже была отключена.