使用 numpy 将 python 转换为使用 opencv 的 c++

Convert python with numpy to c++ with opencv

我正在进行一些优化工作,想将某些部分从 python 转换为 C++

是否可以使用 opencv 将此代码转换为 C++?

python代码使用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]]

更新

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;
}

这是 C++11 中的等效代码。这应该比您的 python 代码快几倍。

#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);
}

还有一些补充说明。

注1:由于python和std的shuffle算法不同,结果不完全一样。

注意2:使用您的代码,num_samples不能大于输入图像中的像素数,这似乎是一个错误。请检查 samples.

的长度

注3:在这两种实现中,最昂贵的部分是shuffle。 python 的 60% 和 C++ 的 80% 以上都花在了这里。如果您想进一步优化,这绝对是您应该利用的地方。