以最快的速度获取字符串中图像的所有像素数据

Posted

技术标签:

【中文标题】以最快的速度获取字符串中图像的所有像素数据【英文标题】:Get all pixel data of an image in a string as quickly as possible 【发布时间】:2021-05-07 19:31:24 【问题描述】:

我需要在字符串中获取图像的所有像素数据,每个像素占用 6 个字符,每个 RGB 通道 2 个,我将它们存储在 HEX 中,因此 0-255 可以写为 00- FF,因此,例如,全白像素为“ffffff”,全黑像素为“000000”。

这是我目前拥有的代码,使用 OpenCV,288x160 图像大约需要 300 毫秒:

Mat image = imread("image.jpg");

resize(image, image, Size(288, 160));

Vec3b buf;

stringstream ss;

auto start = high_resolution_clock::now();

for (int i = 0; i < image.rows; i++) 
    for (int j = 0; j < image.cols; j++) 
        buf = image.at<Vec3b>(i, j);
        ss << hex << setfill('0') << setw(2) << (int) buf[0] << setw(2) << (int) buf[1] << setw(2) << (int) buf[2];
    


string output = ss.str();

auto stop = high_resolution_clock::now();

auto duration = duration_cast<milliseconds>(stop - start);

cout << "Execution time: " << duration.count() << " ms" << endl;

还有其他更好/更快的方法吗?我知道这个概念本身效率不高,但我真的需要从中得到一个字符串,300ms 并不是那么糟糕,但越快越好

【问题讨论】:

【参考方案1】:

如果速度是一个问题,那么完全摆脱stringstream,只需手动填充string,使用一些位移来计算十六进制数字,例如:

Mat image = imread("image.jpg");
resize(image, image, Size(288, 160));

const char *hexDigits = "0123456789abcdef";

auto start = high_resolution_clock::now();

string output((image.rows * image.cols) * 6, '\0');
size_t idx = 0;

for (int i = 0; i < image.rows; ++i) 
    for (int j = 0; j < image.cols; ++j) 
        Vec3b &buf = image.at<Vec3b>(i, j);
        for(int k = 0; k < 3; ++k) 
            uchar ch = buf[k];
            output[idx++] = hexDigits[(ch >> 4) & 0x0F];
            output[idx++] = hexDigits[ch & 0x0F];
        
    


auto stop = high_resolution_clock::now();

auto duration = duration_cast<milliseconds>(stop - start);

cout << "Execution time: " << duration.count() << " ms" << endl;

或者,这个循环可能会减少几毫秒,因为不必为每个单独的像素调用image.at()

for (int i = 0; i < image.rows; ++i) 
    Vec3b *buf = image.ptr<Vec3b>(i, 0);
    const Vec3b* buf_end = buf + image.cols;
    while (buf != buf_end) 
        for(int k = 0; k < 3; ++k) 
            uchar ch = (*buf)[k];
            output[idx++] = hexDigits[(ch >> 4) & 0x0F];
            output[idx++] = hexDigits[ch & 0x0F];
        
        ++buf;
    

【讨论】:

这个解决方案真的很好用,现在同一张图片的执行时间大约是20ms,我只有一个问题,我们不需要在字符串的大小上加1来解释'\0'?我对 C++ tbh 并没有真正的经验,我只知道一点 C "我们不需要在字符串的大小上加 1 来说明 '\0' 吗?" - 不,std::string 不是 C细绳。它将在内部为您处理'\0'

以上是关于以最快的速度获取字符串中图像的所有像素数据的主要内容,如果未能解决你的问题,请参考以下文章

MATLAB中图像的对角线像素

Opencv中图像的遍历与像素操作

如何获取 Cakephp 中图像的完整 URL?

画布中图像的 CORS 设置

在鼠标移动时获取fabric.js中图像像素的rgb值

无法读取 C 中图像的所有字节 [重复]