【发布时间】:2019-11-06 21:31:15
【问题描述】:
我是 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?
【问题讨论】:
-
My_transform的实现是什么?您可以重写它以利用 OpenCV 支持的现有矢量化操作。否则,您卷起袖子直接处理底层缓冲区并手动对其进行矢量化(使用 SSE 或 AVX)。 -
内存带宽不可能是这里的限制。这是一个线性扫描,大部分时间读取可能来自 L1 缓存。您只是一次处理一小块数据(迭代器中可能存在一些开销,但我从未测量过)。
-
转换正在开发中,尚未明确定义。
-
好的,那么您首先需要完成转换算法的定义,因为这是大部分工作所在。在此之前,您唯一能做的有意义的事情就是重写该循环以使用
cv::Mat::forEach,这将利用所有 CPU 内核。
标签: image opencv memory 64-bit mat