【opencv】——Mat data的排列样式 || 深度学习矩阵排列注意事项

转载自:https://zhuanlan.zhihu.com/p/258369721

1.Mat排列

Mat是一种图像容器,是二维向量,灰度图的Mat一般存放类型,RGB彩色图像一般存放类型。

单通道灰度图数据存放样式:
在这里插入图片描述

RGB三通道彩色图存放形式不同,每列并列存放通道数量的子列(注意通道数量反转为了BGR):
在这里插入图片描述

通常情况下Mat的每一行是连续存放的,也就是在内存上图像的所有数据存放成一行,在用指针访问时可以提供很大方便。可以用 isContinuous()函数来判断图像数组是否为连续的,语句为

if (img.isContinuous()){}

2. mat转深度学习矩阵注意事项

从上面可以看出opencv rgb mat的排列方式为:

R G B R G B ......

而深度学习矩阵要求输入的数据是,R,G,B依次连续排列的。

R R R......G G G......B B B

这里可以看别人用cuda写的一个resizeandnorm函数:

#include <cuda_runtime.h>
#include <device_launch_parameters.h>
#include <resize.h>
#include <stdio.h>
__forceinline__ __device__ float3 get(uchar3* src, int x,int y,int w,int h){
    if(x < 0 || x>=w || y<0 || y>=h) return make_float3(0.5,0.5,0.5);
    uchar3 temp = src[y*w + x];
    return make_float3(float(temp.x)/255.,float(temp.y)/255.,float(temp.z)/255.);
}

__global__ void resizeNormKernel(uchar3* src,float *dst,int dstW, int dstH,int srcW,int srcH,
                                                float scaleX, float scaleY,float shiftX, float shiftY) {
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
    const int x = idx % dstW;
    const int y = idx / dstW;
    if (x >= dstW || y >= dstH)
        return;
    float w = (x - shiftX + 0.5) * scaleX - 0.5;        // 缩放的反向映射矩阵
    float h = (y - shiftY + 0.5) * scaleY - 0.5;        // opencv 
    int h_low = (int)h;
    int w_low = (int)w;
    int h_high = h_low + 1;
    int w_high = w_low + 1;
    float lh = h - h_low;
    float lw = w - w_low;
    float hh = 1 - lh, hw = 1 - lw;
    float w1 = hh * hw, w2 = hh * lw, w3 = lh * hw, w4 = lh * lw;
    float3 v1 = get(src,w_low,h_low,srcW,srcH);
    float3 v2 = get(src,w_high,h_low,srcW,srcH);
    float3 v3 = get(src,w_low,h_high,srcW,srcH);
    float3 v4 = get(src,w_high,h_high,srcW,srcH);
    int stride = dstW*dstH;
    dst[y*dstW + x] = w1 *v1.x + w2 * v2.x + w3 *v3.x + w4 * v4.x ;
    dst[stride + y*dstW + x] = w1 *v1.y + w2 * v2.y + w3 *v3.y + w4 * v4.y ;
    dst[stride*2 + y*dstW + x] = w1 *v1.z + w2 * v2.z + w3 *v3.z + w4 * v4.z;
}

int resizeAndNorm(void * p,float *d,int w,int h,int in_w,int in_h, bool keepration ,bool keepcenter,cudaStream_t stream){
    float scaleX = (w*1.0f / in_w);
    float scaleY = (h*1.0f / in_h);
    float shiftX = 0.f ,shiftY = 0.f;
    if(keepration)scaleX = scaleY = scaleX > scaleY ? scaleX : scaleY;
    if(keepration && keepcenter){shiftX = (in_w - w/scaleX)/2.f;shiftY = (in_h - h/scaleY)/2.f;}
    const int n = in_w*in_h;
    int blockSize = 1024;
    const int gridSize = (n + blockSize - 1) / blockSize;
    resizeNormKernel<<<gridSize, blockSize, 0, stream>>>((uchar3*)(p),d,in_w,in_h,w,h,scaleX,scaleY,shiftX,shiftY);
    return 0;
}

以下三行就是进行数据重排:
dst[y*dstW + x] = w1 *v1.x + w2 * v2.x + w3 v3.x + w4 * v4.x ;
dst[stride + y
dstW + x] = w1 v1.y + w2 * v2.y + w3 v3.y + w4 * v4.y ;
dst[stride
2 + y
dstW + x] = w1 *v1.z + w2 * v2.z + w3 *v3.z + w4 * v4.z;

3. npp中的处理

针对32位float型的数据,使用

nppiCopy_32s_C3P3R (const Npp32s *pSrc, int nSrcStep, Npp32s *const aDst[3], int nDstStep, NppiSize oSizeROI)

Split a packed multi-channel image into multiple single channel planes.

E.g. copy the three channels of an RGB image into three separate single-channel images.

中文翻译为:将一个压缩的多通道图像分割成多个单通道平面

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
OpenCV中,Mat是一个非常重要的类,它用于表示图像或矩阵数据。可以使用不同的方法来创建Mat对象。其中一种方法是使用构造函数,如Mat img(100,100,CV_8UC3, Scalar(255,255,255)),这会创建一个大小为100x100的3通道图像,像素值为(255,255,255)。另一种方法是使用create()函数,如img.create(100,100, CV_8UC3),这也会创建一个大小为100x100的3通道图像。此外,还可以使用zeros()、eye()和ones()函数来创建全零矩阵、对角为1的对角矩阵和全1矩阵。还可以使用逗号数组的方式来创建对象,如Mat img = (Mat_<double>(2,2) << 0,1,1,0)。这种方式按行填充数据。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [opencv mat介绍](https://download.csdn.net/download/cockcomputer/10833601)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [OpenCVMat的详细介绍](https://blog.csdn.net/PRML_MAN/article/details/124482661)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [openCV学习(一)——Mat类详解](https://blog.csdn.net/lvyaer_1122/article/details/124454244)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值