opencv图片保存0字节_OpenCV图像数据字节对齐

[TOC]

图像数据是否做字节对齐,可能影响到逐像素的遍历操作。OpenCV中的图像是HWC维度顺序存储,我们需要注意WC维度是否做4字节对齐。

这里使用的测试图如下:

注意它的宽度是471像素,是不能被4整除的。

1. IplImage的data字段,是char*类型,是4字节对齐。

const char* im_pth = "image.png";

IplImage* im = cvLoadImage(im_pth);

img->widthStep等于align_up(im->width*im->channels) //向上取整到最近的4的倍数

e.g. width=471, channels=3, widthStep=1416

2. 手动创建的Mat通常是没有字节对齐的

e.g.

FcImage fc_im = fc_load_image(im_pth);

int im_h = fc_im.h;

int im_w = fc_im.w;

int im_c = fc_im.c;

cv::Mat image = cv::Mat();

image.create(im_h, im_w, CV_8UC3);

cout << image.step << endl; //1413

来看看不对齐是什么效果,这里使用了fc image,提供的是对齐的图像数据,然后拷贝给手动创建的Mat,也就是不做对齐的:

FcImage fc_im = fc_load_image(im_pth);

int im_h = fc_im.h;

int im_w = fc_im.w;

int im_c = fc_im.c;

cv::Mat image = cv::Mat();

image.create(im_h, im_w, CV_8UC3);

for (int h = 0; h < im_h; h++) {

for (int w = 0; w < im_w; w++) {

for (int c = 0; c < im_c; c++) {

int src_idx = h * im_w*im_c + w * im_c + c;

int dst_idx = h * im_w*im_c + w * im_c + c;

image.data[dst_idx] = fc_im.data[src_idx];

}

}

}

std::cout << image.step << std::endl;

cv::imshow("image", image);

cv::waitKey(0);

3. 从IplImage转过来的Mat,是字节对齐的

早期的opencv2可以这样写:

const char* im_pth = "image.png";

IplImage* ipl = cvLoadImage(im_pth);

Mat mat(ipl); //或Mat mat(ipl, true)表示拷贝数据

后来的opencv不让这么写了,需要用cvarrayToMat函数:

IplImage* ipl = cvLoadImage(im_pth);

int im_h = ipl->height;

int im_w = ipl->width;

cv::Mat mat = cv::cvarrToMat(ipl);

cv::imshow("image", mat);

cv::waitKey(0);

4. 总结

如果需要逐像素操作,那么最好是定义并使用linebytes属性来替代每一处使用到的im_width*im_channel,因为linebytes=align_up(im_width*im_channel, 4)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值