opencv图像数据操作

1.imread

cv::Mat img;

img = cv::imread(image_path, CV_LOAD_IMAGE_COLOR); // image_path为图片存储路径

if (!img.data || !seg.data) {
    std::cout << "Could not open or find file " << image_path << std::endl;
    return;
}

2.单个像素的操作

a single channel grey scale image (type 8UC1) and pixel coordinates x and y:

int b = (int) img.at<uchar>(y, x);  // 占一个字节:uchar,  占四个字节:float。 

                                    // opencv Mat 是按行存的。


three channel image with BGR color ordering

Vec3b intensity = img.at<Vec3b>(y, x);
uchar blue = intensity.val[0];
uchar green = intensity.val[1];
uchar red = intensity.val[2];

---未经验证

cv::Vec3b intensity = img.at<cv::Vec3b>(y, x); 

...

---------------------------------------------------------------------------------------------------------------------
代码示例:整行读取,逐个像素赋值。特别注意数据类型对应
#include <opencv2/highgui/highgui_c.h>
#include <stdint.h>

#include <algorithm>
#include <map>
#include <string>
#include <utility>
#include <vector>
#include <fstream>
#include <iostream>
#include <sstream>
#include <math.h>

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

int main(){
     cv::Mat img ;
     cv::Mat dsm ;
     std::string image_path = "top_mosaic_09cm_area1.tif" ;        // uint8, 三个通道
     std::string dsm_path     = "dsm_09cm_matching_area1.tif" ;   // single, 单通道的
     
     img = cv::imread( image_path, CV_LOAD_IMAGE_COLOR );
     dsm = cv::imread( dsm_path, CV_LOAD_IMAGE_UNCHANGED ) ;  
                                 //here, dsm is single type image. may be decimal representation.
     
     if (!img.data || !dsm.data) {
        std::cout << "Could not open or find file " << image_path << " or " << dsm_path << std::endl ;   
        return 1 ;
     }
     
     std::cout << "top.channels= " << img.channels() << std::endl ;
     std::cout << "dsm.channels= " << dsm.channels() << std::endl ;
     
     std::cout << "dsm.rows=" << dsm.rows << " dsm.cols = " << dsm.cols << std::endl ;
     
     cv::Mat img_concate( 2569, 1919, CV_32FC(4), cv::Scalar::all(0) ) ;   
                                        // 前两个为top_mosaic_09cm_area的高和宽
     const uchar* img_ptr;
     const float* dsm_ptr;      // 注意数据类型
     int top_index;
     for ( int h=0; h<img.rows; h++)
     {
       img_ptr = img.ptr<uchar>(h);  // 读取一行。每行存储方式:每个点三通道连续读:bgr  bgr  bgr ... 存储方式。
       dsm_ptr = dsm.ptr<float>(h);   // the data type should be right 
       int img_index = 0;
       int dsm_index = 0;
       for ( int w=0; w<img.cols; w++)
       {
          for ( int c=0; c<3; c++ ){
          top_index = (c*img.rows + h )*img.cols + w ;
          float pixel =  float ( img_ptr[ img_index++ ] ) ;   
          img_concate.data[ top_index ] =  pixel  ;     
        you should know how to assign values to cv::Mat., 逐个像素存入连续的内存
      //  std::cout << "img concate " << float ( img_concate.data[ top_index ] ) << std::endl ; // Mat数据,转化类型后再输出
          } 
          top_index   = ( 3*img.rows + h ) * img.cols + w ;    // 第四个通道上(h,w)位置上的索引,  img_concate
          float pixel = dsm_ptr[ dsm_index++ ] ;                   
       // 逐个读取dsm一行dsm_ptr中的像素值,由于为连续存储,故采用自加方式。注意数据类型对应。
          img_concate.data[ top_index ] = pixel ;                   // 存第四个通道上的数值
     //     std::cout << "img concate " << float ( img_concate.data[ top_index ] ) << std::endl;
       }
     } 
     std::cout <<  "hello, world!" << std::endl ;
     return 1; 
}

3.resize

cv::Size rescaleSize( resize_w, resize_h );
cv::resize(img, img, rescaleSize, 0, 0, cv::INTER_LINEAR) ;

4.copyTo

cv::Rect roi;
roi.x = 0;  
roi.y = 0;
roi.height = floor(img.rows / 2);   
roi.width  = floor(img.cols / 2);

cv::Mat crop_img;

img(roi).copyTo(crop_img);

关于Mat数据复制:前面说过Mat包括头和数据指针,当使用Mat的构造函数初始化的时候,会将头和数据指针复制(注意:只是指针复制,指针指向的地址不会复制),若要将数据也复制,则必须使用copyTo或clone函数

5.存储:按行存的

遍历图像

int h,w,c;

for (h=0; h<height; h++)

   for (w=0; w<width; w++)

      for(c=0; c<channel; c++)

         top_index = (h*width+w)*channel+c; // 即:先channel, 再宽,再高

注:上述遍历自己没有亲自测试?

在输出uchar类型时,需先将其转化为整型(int)...

-----------------------------------------------

为了加快访问的速度,openCV往往会在内存中将像素数据连续地存储成一行,isContinus()函数的作用就是用于判断是否连续存储成一行。存储成一行有什么好处呢?给定这行的头指针p,则只要使用p++操作就能逐个访问数据。

因此当判断存放在一行的时候,可以通过数据指针++很容易遍历图像像素:

long nRows = M.rows * M.channels();  // channels()也是Mat中一个常用的函数,用于获取通道数(RGB=3,灰度=1)
long nCols = M.cols;
uchar *p = M.data;  // 数据指针
if(M.isContinuous())
{
    nCols *= nRows;
    for (long i=0; i < nCols; i++) {
        *p++ = ...; // 像素赋值或读取操作
    }       
}

请注意以上几个常用的Mat成员遍历和函数:

M.row; // 返回图像行数
M.nCols;  // 返回图像列数
M.channels();  //返回通道数
M.isContinuous(); // 返回bool类型表示是否连续存储

部分摘自

http://docs.opencv.org/2.4/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html?highlight=accessing%2520element

http://xiahouzuoxin.github.io/notes/html/OpenCV%E5%9F%BA%E7%A1%80%E7%AF%87%E4%B9%8BMat%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84.html

扩展阅读

OpenCV中对Mat里面depth,dims,channels,step,data,elemSize和数据地址计算的理解 https://www.douban.com/note/265479171/

--------------------------------------------------------------------------------------------------------------------------------------------------------------
当图像的数值超过255时的处理:
对于matlab而言:pca_gray      =   uint8( 255*mat2gray(pca_im(:,:,1)) ) ;             % the PC first is transformed to gray image, then gabor.
对于opencv而言:可以将图像矩阵存成.txt文件进行查看。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值