I'm working on some optimazation and want to convert some parts from python to c
Is it possible to convert this code to c with opencv
?
The python code uses numpy
import numpy as np
from PIL import Image
pil_img = Image.open(input_filename)
img = np.array(pil_img)
pixels = img.reshape((-1, 3))
num_pixels = pixels.shape[0]
num_samples = int(num_pixels*5)
idx = np.arange(num_pixels)
np.random.shuffle(idx)
samples = pixels[idx[:num_samples]]
update
std::vector<uchar> sample_pixels(const cv::Mat& m, int sample_percent=5){
assert(m.isContinuous());
const auto* input = m.ptr<uchar>();
int
num_pixels = m.total(),
num_samples = num_pixels * sample_percent;
std::cout
<< "num pixels: " << num_pixels << '\n'
<< "num samples: " << num_samples << '\n';
std::vector<uchar> samples(num_samples);
// Fills idx with sequentially increasing values
std::vector<int> idx(num_pixels);
std::iota(idx.begin(), idx.end(), 0);
// Shuffle idx
std::mt19937 engine(0);
std::shuffle(idx.begin(), idx.end(), engine);
for(int i = 0; i < num_samples; i ){
//samples[i] = input[idx[i]];
}
//auto output_mat = cv::Mat(samples, false);
//cv::imwrite("enhance-samples.png", output_mat);
return samples;
}
CodePudding user response:
This is the equivalent code in C 11. This should be several times faster than your python code.
#include <random>
#include <numeric>
#include <opencv2/opencv.hpp>
void shuffling(const std::string &input_filename, const std::string &output_filename) {
// ========== UPDATE ==========
const cv::Mat plain_input_mat = cv::imread(input_filename, -1);
// Equivalent to img.reshape((-1, 3))
const cv::Mat input_mat = plain_input_mat.reshape(3);
// ============================
// By doing this, you can access the pixels without any extra checks.
assert(input_mat.isContinuous());
const auto *input = input_mat.ptr<cv::Vec3b>();
const auto num_samples = input_mat.total();
std::vector<cv::Vec3b> output(num_samples);
std::vector<int> idx(input_mat.total());
std::iota(idx.begin(), idx.end(), 0); // Equivalent to arange.
// Note: numpy uses PCG64 which does not exist in the std library.
std::mt19937 engine(0);
std::shuffle(idx.begin(), idx.end(), engine);
for (int i = 0; i < num_samples; i ) {
output[i] = input[idx[i]];
}
// Save as an image if necessary.
auto output_mat = cv::Mat(output, false);
cv::imwrite(output_filename, output_mat);
}
There are a couple of additional notes.
Note1: Due to the difference in the shuffle algorithm between python and std, the results are not exactly the same.
Note2: With your code, num_samples
cannot be larger than the number of pixels in the input image, which seems to be a bug. Please check the length of the samples
.
Note3: In both implementations, the most expensive part is shuffle
. 60% for python and more than 80% for C is spent here. If you want to optimize further, this is definitely where you should exploit.