首页 > 解决方案 > 使用 64 位操作在 openCV 中每次读/写访问多个像素

问题描述

我是openCV的新手。我正在编辑图像,需要在图像的大矩形块上读取和写入连续像素,而不是整个图像。我的输入图像是单通道灰度,CV_16UC1 作为输入,CV_8UC1 作为输出。我目前正在使用 MatConstIterator_ 访问像素。

Mat image, image_read = imread(infilename, 0);
image_read.convertTo(image, CV_16UC1);
//...define img_dim_y, img_dim_x
Mat imout(img_dim_y, img_dim_x, CV_8UC1);

MatConstIterator_<uint16_t> pin = imageIn.begin<uint16_t>(), pixel_in_end = imageIn.end<uint16_t>();
MatIterator_<uint8_t> pixel_out = imageOut.begin<uint8_t>();
for(; /*selected pixel in a patch*/; ++pixel_out , ++pixel_out)
        *pixel_out = My_transform(*pixel_in);

这是内存带宽有限的,并且所有时间都以每像素 10 微秒的速率读取和写入像素。我的机器非常现代,所以这比 ~MHz ram 时钟慢得多。对于 64 位机器,应该可以一次读入 4 个 16 位像素,一次写出 8 个 8 位像素,使用几个移位操作。这将使流水线速度至少提高 4-5 倍。如何哄骗这些数据进出 openCV Mat?

标签: imageopencvmemory64-bitmat

解决方案


我找到了一种方法来做这样的事情。以下将一次读取 4 个像素,但在读取一小部分图像后,它会在随机位置出现段错误。

//For a Mat img formatted as a CV_16UC1
uint8_t* alignas(64) Data = (uint8_t*)img.data;
for(int i = 0; /*selected pixel in a patch*/; i += 8){
    uint16_t p0, p1, p2, p3; //pixels
    uint64_t word = reinterpret_cast<uint64_t*>(Data)[i];
    p0 =  (word & 0x00000000000000FF)        + ((word & 0x000000000000FF00) >> 8);
    p1 = ((word & 0x0000000000FF0000) >> 16) + ((word & 0x00000000FF000000) >> 24);
    p2 = ((word & 0x000000FF00000000) >> 32) + ((word & 0x0000FF0000000000) >> 40);
    p3 = ((word & 0x00FF000000000000) >> 48) + ((word & 0xFF00000000000000) >> 56);
    //do things with pixels
}

推荐阅读