Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在OpenCV中循环16位Mat像素的有效方法_C++_Opencv_Image Processing - Fatal编程技术网

C++ 在OpenCV中循环16位Mat像素的有效方法

C++ 在OpenCV中循环16位Mat像素的有效方法,c++,opencv,image-processing,C++,Opencv,Image Processing,我正在尝试在16位灰度OpenCV Mat上进行非常简单(类似LUT)的操作,这是高效的,并且不会降低调试器的速度 虽然有一个解决这个问题的方法,但它没有指出这些方法中的大多数只适用于8位图像(包括完美、优化的LUT函数) 我尝试了以下方法: uchar* p = mat_depth.data; for (unsigned int i = 0; i < depth_width * depth_height * sizeof(unsigned short); ++i) { *p =

我正在尝试在16位灰度OpenCV Mat上进行非常简单(类似LUT)的操作,这是高效的,并且不会降低调试器的速度

虽然有一个解决这个问题的方法,但它没有指出这些方法中的大多数只适用于8位图像(包括完美、优化的LUT函数)

我尝试了以下方法:

uchar* p = mat_depth.data;
for (unsigned int i = 0; i < depth_width * depth_height * sizeof(unsigned short); ++i)
{
    *p = ...;
    *p++;
}
uchar*p=mat_depth.data;
for(无符号整数i=0;i
非常快,不幸的是只支持uchart(就像LUT)


inti=0;
对于(int row=0;row
改编自此答案:。对我不起作用,而且速度很慢


cv::MatIterator\uuit,结束;
for(it=mat_depth.begin(),end=mat_depth.end();it!=end;+it)
{
*它=。。。;
}
工作正常,但是它使用了大量的CPU,使得调试器非常慢


这个答案向用户指出,但是它只提到高级优化技术,如IPP和OpenCL

我要寻找的是一个非常简单的循环,就像第一个代码一样,但是对于ushorts


你推荐什么方法来解决这个问题?我并不是在寻找极端的优化,仅仅是与单for for循环的性能相符合。数据。

< p>您的问题的最佳解决方案已经在您提到的教程中写入了,该章节被命名为“有效方式”。您所需要的只是用ushort替换uchar的每个实例。不需要其他更改。

OpenCV实现基于多态性和通过模板的运行时调度。在OpenCV版本中,模板的使用仅限于一组固定的基本数据类型。也就是说,数组元素应具有以下类型之一:

  • 8位无符号整数(uchar)
  • 8位有符号整数(SCAR)
  • 16位无符号整数(ushort)
  • 16位有符号整数(短)
  • 32位有符号整数(int)
  • 32位浮点数(浮点)
  • 64位浮点数(双精度)
  • 多个元素的元组,其中所有元素都具有相同的类型(上述元素之一)
如果继续使用
cv::Mat
,则可以使用指针算法遍历整个数据指针,并且只应使用指向
cv::Mat
的适当指针类型。 此外,请记住,
cv::Mat
s并不总是连续的(它可以是ROI、填充或从像素指针创建的),用指针在它们上迭代会崩溃

循环示例:

cv::Mat cvmat16sc1 = cv::Mat::eye(10, 10, CV_16SC1);

if (cvmat16sc1.data)
{
    if (!cvmat16sc1.isContinuous())
    {
        cvmat16sc1 = cvmat16sc1.clone();
    }

    short* ptr = reinterpret_cast<short*>(cvmat16sc1.data);
    for (int i = 0; i < cvmat16sc1.cols * cvmat16sc1.rows; i++, ptr++)
    {
        if (*ptr == 1)
            std::cout << i << ": " << *ptr << std::endl;
    }
}
cv::Mat cvmat16sc1=cv::Mat::eye(10,10,cv_16SC1);
if(cvmat16sc1.数据)
{
如果(!cvmat16sc1.isContinuous())
{
cvmat16sc1=cvmat16sc1.clone();
}
short*ptr=重新解释铸件(cvmat16sc1.数据);
对于(int i=0;i我实现了Michael和Kornel的建议,并在发布和调试模式下对它们进行了基准测试

代码:

cv::Mat LUT_16(cv::Mat &mat, ushort table[])
{
    int limit = mat.rows * mat.cols;

    ushort* p = mat.ptr<ushort>(0);
    for (int i = 0; i < limit; ++i)
    {
        p[i] = table[p[i]];
    }
    return mat;
}

cv::Mat LUT_16_reinterpret_cast(cv::Mat &mat, ushort table[])
{
    int limit = mat.rows * mat.cols;

    ushort* ptr = reinterpret_cast<ushort*>(mat.data);
    for (int i = 0; i < limit; i++, ptr++)
    {
        *ptr = table[*ptr];
    }
    return mat;
}

cv::Mat LUT_16_if(cv::Mat &mat)
{
    int limit = mat.rows * mat.cols;

    ushort* ptr = reinterpret_cast<ushort*>(mat.data);
    for (int i = 0; i < limit; i++, ptr++)
    {
        if (*ptr == 0){
            *ptr = 65535;
        }
        else{
            *ptr *= 100;
        }
    }
    return mat;
}

ushort* tablegen_zero()
{
    static ushort table[65536];
    for (int i = 0; i < 65536; ++i)
    {
        if (i == 0)
        {
            table[i] = 65535;
        }
        else
        {
            table[i] = i;
        }
    }
    return table;
}
cv::Mat LUT_16(cv::Mat&Mat,ushort表格[])
{
int limit=mat.rows*mat.cols;
ushort*p=材料ptr(0);
对于(int i=0;i
结果如下(发布/调试):

  • LUT_16:0.202毫秒/0.773毫秒
  • LUT_16_重新解释投射:0.184 ms/0.801 ms
  • LUT_16_if:0.249毫秒/0.860毫秒
因此,结论是,在发布模式下,reinterpret_cast的速度快9%,而在调试模式下,ptr的速度快4%

同样有趣的是,直接调用if函数而不是应用LUT只会使其速度降低0.065ms

规格:流式640x480x16位灰度图像,Visual Studio 2013,i7 4750HQ

cv::Mat cvmat16sc1 = cv::Mat::eye(10, 10, CV_16SC1);

if (cvmat16sc1.data)
{
    if (!cvmat16sc1.isContinuous())
    {
        cvmat16sc1 = cvmat16sc1.clone();
    }

    short* ptr = reinterpret_cast<short*>(cvmat16sc1.data);
    for (int i = 0; i < cvmat16sc1.cols * cvmat16sc1.rows; i++, ptr++)
    {
        if (*ptr == 1)
            std::cout << i << ": " << *ptr << std::endl;
    }
}
cv::Mat LUT_16(cv::Mat &mat, ushort table[])
{
    int limit = mat.rows * mat.cols;

    ushort* p = mat.ptr<ushort>(0);
    for (int i = 0; i < limit; ++i)
    {
        p[i] = table[p[i]];
    }
    return mat;
}

cv::Mat LUT_16_reinterpret_cast(cv::Mat &mat, ushort table[])
{
    int limit = mat.rows * mat.cols;

    ushort* ptr = reinterpret_cast<ushort*>(mat.data);
    for (int i = 0; i < limit; i++, ptr++)
    {
        *ptr = table[*ptr];
    }
    return mat;
}

cv::Mat LUT_16_if(cv::Mat &mat)
{
    int limit = mat.rows * mat.cols;

    ushort* ptr = reinterpret_cast<ushort*>(mat.data);
    for (int i = 0; i < limit; i++, ptr++)
    {
        if (*ptr == 0){
            *ptr = 65535;
        }
        else{
            *ptr *= 100;
        }
    }
    return mat;
}

ushort* tablegen_zero()
{
    static ushort table[65536];
    for (int i = 0; i < 65536; ++i)
    {
        if (i == 0)
        {
            table[i] = 65535;
        }
        else
        {
            table[i] = i;
        }
    }
    return table;
}