OpenCV直方图颜色匹配Python转C++输出异常问题求助
OpenCV直方图颜色匹配C++实现问题排查
我尝试实现OpenCV颜色匹配功能,参考对应Python版本逻辑改写的C++代码运行结果不符合预期,相关代码和测试信息如下:
Python参考实现(无mask选项)
#!/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 Mat& 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++) { { float& 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(&Flatten(src[0]), 1, 0, Mat(), src_hist_blue, 1, &histSize, &histRange, uniform, accumulate); calcHist(&Flatten(src[1]), 1, 0, Mat(), src_hist_green, 1, &histSize, &histRange, uniform, accumulate); calcHist(&Flatten(src[2]), 1, 0, Mat(), src_hist_red, 1, &histSize, &histRange, uniform, accumulate); calcHist(&Flatten(ref[0]), 1, 0, Mat(), ref_hist_blue, 1, &histSize, &histRange, uniform, accumulate); calcHist(&Flatten(ref[1]), 1, 0, Mat(), ref_hist_green, 1, &histSize, &histRange, uniform, accumulate); calcHist(&Flatten(ref[2]), 1, 0, Mat(), ref_hist_red, 1, &histSize, &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代码转C++的过程中哪里存在问题,恳请帮忙排查。
内容的提问来源于stack exchange,提问作者Michael Chourdakis
相关产品推荐
相关产品推荐

