首先对于任何一个二维图像,加载入内存后都能看作一个二维像素数组。假如是一张8位图像,它的每个像素值可以用一个0~255的unsigned char表示,也就是说图像可以看成一个unsigned char的数组。假设它的长和宽分别为width和height,那么这个图像用byte B[height,width](c#二维数组)或者用unsigned char B[height][width](C++二维数组)来表示就非常的恰当。推而广之,假如是一个长宽高分别是width、height和depth的三维图像,那么就可以采用三维数组来byte B[depth,height,width](C#)或者unsigned char B[depth][height][width](C++)来表示。

  由于内存地址实际上是线性的,在计算机里面多维数组都是用一维数组的方式组织的,实际上,若使用二维数组B[a][b]。对于一个长宽分别为b和a的位图B,内存中实际上是一个线性排列的布局,也就是说计算机会把一个二维数组看成是数组的数组,一个三维的数组就是数组的数组的数组。例如二维数组unsigned char B[height][width] ,内存中的就是height个长度为width的数组,那么假如数组的初始地址为B,那么B[i][j]的实际存储位置是在i个width后面再加j个位置。所以我们若把二维数组一维化,我们可以把B声明为一个一维数组 unsigned char B[width*height],当我们取第i行j列的像素的时候,就使用B[i*width+j]这个表达式。

  这里有一个问题,为什么要讨论二维和三维图像的一维化,直接使用多维数组行吗?其实图像都统一使用一维数组的表达方式,很大程度是因为IO原因。因为对于一张位图,或者是.raw格式的无压缩图像,在读取图像的时候都是使用一维数组作为缓冲区(比如c语言的fread函数 size_t fread ( void *buffer, size_t size, size_t count, FILE *stream) 中的buffer就是个一维数组)那么将图像文件读为一维数组后,一般为了避免不必要的开销,就不会再把这个数组的值按位置一一复制到一个二维数组去,而是直接使用这个一维数组。实际上,使用二维、三维数组作为二维、三维图像的存储结构也完全没有问题。只是在遇到这两种不同方式的时候,记住二维的B[j][i]对应于一维的B[i*width+j],三维的B[k][j][i]对应于一维的B[i+j*width+k*width*height]即可。

  下面的代码是用C++封装了二维或三维图像的相关属性、方法和数据。可以看出,图像最基本要有长宽高这些表示尺寸的属性,然后需要一个表示像素类型的类别PixelType。对于8位图像,一般使用char或 unsigned char表示像素类型。对于16位或者32位图像,既可以用C++语言相应长度的short和int/float变量来表示,也可以声明一个新结构体,由若干个char或unsigned char成员来组成。使用结构体也是比较常用的方法,比如对于ARGB图像而言使用的PixelType是一个有四个unsigned char成员的结构体,这样这四个成员能分别表示对应的颜色的A、R、G、B分量。图像结构体中当然还必须有指向图像数据的指针*B,同时还要提供存取像素的方法。

#define T PixelType
struct Bitmap2D
{T  *B;int width;int height;void SetPixel(int,int,T);T GetPixel(int,int);
}
struct Bitmap3D
{T  *B;int width;int height;int depthvoid SetPixel(int,int,int,T);T GetPixel(int,int,int);
}

  综合以上所述,对于二维图像j行i列的像素的操作的伪代码如下:

GetPixel(i,j)return B[i+width*j]SetPixel(i,j,v)B[i+width*j]=v

  三维图像k层j行i列的像素存取方式如下:

GetPixel(i,j,k)return B[i+width*j+width*height*k]SetPixel(i,j,k,v)B[i+width*j+width*height*k]=v

附 三维图像

  二维图像在平时使用计算机的时候比较常见,相比之下三维图像一般只出现在专业图像领域。对于三维图像可以有很多表现形式,比如图像序列(N张大小一样的二维图),RAW体数据(三维数组文件)等。如本文用作测试的三维图像Lobster.raw数据,来自www.volvis.org,是用CT扫描产生56张宽301高324的图片然后组合在一起的。内部的值偏大的像素集合组成一个三维的龙虾形状。

  不像二维图片能直接完整的在屏幕上显示,想观察三维图像的内容一般得采用特别的办法。一种是观察某一维切片,比如如下的图就是lobster数据分别在Z轴上取5-10-15-....-55的切片制作的动态图。

  用体绘制软件ParaView可以用体绘制技术直接在3D场景中观察三维图片的内容:

  

附2:三维图像的IO

  三维图像经常会以.raw文件的形式提供,例如www.volvis.org上的所有sample,解压后都是一个.raw文件。Raw文件其实是存图像最简单的方式,是一种对图像无压缩的存储。实际上,这种格式就是把图像一维化的数组存储成文件,所以可以轻易的写出读取Raw文件的代码。不过由于这个文件不带自描述信息,所以在读的时候一定要清楚所读的文件是多少位的图像,长宽高是多少。例如上图所展示的lobster数据。从数据描述中可知其大小为301×324×56,8位,所以采用C++语言将其读为unsigned char数组的代码如下:

void InitArrayFromVolFile(unsigned char * &data,const char* fileName,int length)
{long dataSize = length;std::FILE* file = fopen(fileName,"rb");if( file == NULL ){printf("open the file failed\n");}fread( data,sizeof(unsigned char),dataSize,file );fclose(file);
}

  再将其输出为文件的代码如下,都是比较简单的读写调用,由此同时可以看出,无论是2维还是3维图像,使用一维数组的方式存数据,对于IO来说是十分方便。

void OutPutVolume(const char* fileName,unsigned char* pointer,int width,int height,int depth)
{    int length=width*height*depth;FILE *const nfile = fopen(fileName,"wb");fwrite(pointer,sizeof(unsigned char),length,nfile);fclose(nfile);
}

  前段时间需要找各种三维图像来做实验,发现这个www.volvis.org及其不稳定,时不时就是服务器关闭了,这样会导致需要数据的时候比较麻烦,所以这里干脆把一些常用的数据下来到博客园贴着,以防不时之需。

数据预览 数据参数 数据描述
Aneurism

256x256x256
1:1:1

Rotational C-arm x-ray scan of the arteries of the right half of a human head. A contrast agent was injected into the blood and an aneurism is present.

http://pan.baidu.com/s/1hqeHkXY

Backpack Scan 16Bits
(12bits set)
512 x 512 x 373
0.9766, 0.9766, 1.25

CT scan of a backpack filled with items.

http://pan.baidu.com/s/1pJO4hwJ

Bonsai

256x256x256
1:1:1

CT scan of a bonsai tree.

http://pan.baidu.com/s/1sjPfZhr

Boston Teapot

256x256x178
1:1:1

CT scan of the SIGGRAPH 1989 teapot with a small version of the AVS lobster inside.

http://pan.baidu.com/s/1qWlS0SO

Colon Phantom 8Bits
512 x 512 x 442
0.9316, 0.9316, 0.5
CT scan of a Colon phantom with several different objects and five pedunculated large polyps in the central object.
http://pan.baidu.com/s/1eQgNj6y
Engine

256x256x128
1:1:1

CT scan of two cylinders of an engine block.

http://pan.baidu.com/s/1dDoWEY1

Foot

256x256x256
1:1:1

Rotational C-arm x-ray scan of a human foot. Tissue and bone are present in the dataset.

http://pan.baidu.com/s/1hqHWORi

Lobster

301x324x56
(1:1:1.4)

CT scan of a lobster contained in a block of resin.

http://pan.baidu.com/s/1gdKaIo7

Head MRI CISS 8Bits
(8bits set)
256 x 256 x 124
0.9, 0.9, 0.9

1.5T MRT 3D CISS dataset of a human head that highlights the CSF (Cerebro-Spinal-Fluid) filled cavities of the head.
We also provide a segmentation of the cerebral ventricular system, where the first (negative) number is the number of all voxels of the segmentation, followed by the voxel array indices of the voxels of the segmentations. Please read the new comment above if you have problems with the voxel indices in the segmenation file.

http://pan.baidu.com/s/1dD67C7R

Neghip

64x64x64
(1:1:1)

Simulation of the spatial probability distribution of the electrons in a high potential protein molecule.

http://pan.baidu.com/s/1sjxvEJr

Colon Prone 8Bits
512 x 512 x 463
0.625, 0.625, 1.0

CT scan of abdomen in prone orientation (back faces ceiling, belly faces table.

http://pan.baidu.com/s/1jGA1kvO

Silicium

98x34x34
(1:1:1)

Simulation of a silicium grid.

http://pan.baidu.com/s/1pcKQ6

Skull

256x256x256
1:1:1

Rotational C-arm x-ray scan of phantom of a human skull.

http://pan.baidu.com/s/1hqqS0tQ

浅谈二维和三维图像数据相关推荐

  1. python读取图像数据流_浅谈TensorFlow中读取图像数据的三种方式

    本文面对三种常常遇到的情况,总结三种读取数据的方式,分别用于处理单张图片.大量图片,和TFRecorder读取方式.并且还补充了功能相近的tf函数. 1.处理单张图片 我们训练完模型之后,常常要用图片 ...

  2. MATLAB3 二维和三维图像的绘制

    这篇文章是我在B站上跟随up主ln异教徒学习时根据其讲的内容和我的理解实践做的笔记,视频原地址如下 数学建模最新教程[0基础]_哔哩哔哩_bilibili 一维的情况y被当做纵坐标 当a是一个行向量或 ...

  3. ML之DR:基于鸢尾花(Iris)数据集利用多种降维算法(PCA/TSVD/LDA/TSNE)实现数据降维并进行二维和三维动态可视化应用案例

    ML之DR:基于鸢尾花(Iris)数据集利用多种降维算法(PCA/TSVD/LDA/TSNE)实现数据降维并进行二维和三维动态可视化应用案例 目录 基于鸢尾花(Iris)数据集利用多种降维算法(PCA ...

  4. MATLAB学习笔记——二维和三维绘图

    MATLAB学习笔记--二维和三维绘图 近期练习matlab的二维和三维绘图,整理一下,以防忘记. 文章目录 MATLAB学习笔记--二维和三维绘图 一.二维绘图 1.plot命令 2.fplot 命 ...

  5. matlab三维选取二维,基于Matlab绘制二维和三维图形以及其他图形控制函数的使用方法...

    Matlab绘图 强大的绘图功能是Matlab的特点之一,Matlab提供了一系列的绘图函数,用户不需要过多的考虑绘图的细节,只需要给出一些基本参数就能得到所需图形,这类函数称为高层绘图函数.此外,M ...

  6. 嵌入式AI —— 6. 为糖葫芦加糖,浅谈深度学习中的数据增广

    没有读过本系列前几期文章的朋友,需要先回顾下已发表的文章: 开篇大吉 集成AI模块到系统中 模型的部署 CMSIS-NN介绍 从穿糖葫芦到织深度神经网络 又和大家见面了,上次本程序猿介绍了CMSIS- ...

  7. 二维和三维CAD设计Autodesk AutoCAD 2021

    Autodesk AutoCAD 2021 是一款Autodesk公司发布的非常强大的二维和三维CAD设计软件.用于二维绘图.详细绘制.设计文档和基本三维设计,现已经成为国际上广为流行的绘图工具.具有 ...

  8. 二维和三维CAD设计Autodesk AutoCAD中文2021/2022/2023

    Autodesk AutoCAD 是全球著名的专业计算机辅助设计软件,用于二维绘图.详细绘制.设计文档和基本三维设计,广泛应用于机械设计.工业制图.工程制图.土木建筑.装饰装潢.服装加工等多个行业领域 ...

  9. MATLAB 的绘图:二维和三维

    本节介绍MATLAB 的两种基本绘图功能:二维平面图形和三维立体图形. 5.1 二维平面图形 5.1.1 基本图形函数 plot 是绘制二维图形的最基本函数,它是针对向量或矩阵的列来绘制曲线的.也就是 ...

最新文章

  1. 事件标志组的删除与状态查询
  2. linux kernel中的cmdline的详细介绍
  3. Spring中如何使用注解来配置Bean?有哪些相关的注解?
  4. JVM初学之堆的内存模型
  5. 【重难点】【Java集合 01】HashMap 和 ConcurrentHashMap
  6. ubuntu16 下 源码配置Lnmp环境
  7. JSP标签JSTL(3)--迭代操作
  8. python写彩票程序30选7_写一个彩票程序:30选7
  9. 微商爆粉2.0全自动批量加人模拟手动操作
  10. linux zip文件解压命令详解
  11. Jenkins下载安装
  12. python编程中的不等于符号_python不等于符号怎么写
  13. ArcGIS裁剪栅格图像(图片)后,图…
  14. (bilibili)b站看不见视频评论区或不显示高级弹幕
  15. Dos界面telnet命令的基本使用
  16. 【暑期每日一题】洛谷 P1551 亲戚
  17. 分部积分法的快速运算 表格法
  18. 【 C++ 技术】 C++ 高性能服务器网络框架设计细节
  19. 优麒麟服务器配置备忘
  20. 一篇相当不错的js function详解 读了一定有收获

热门文章

  1. 期货中的正向交易与反向交易
  2. Archetype是什么?
  3. 出差宝宝给我准备的行李
  4. 程序员鄙视链! | 每日趣闻
  5. Github建仓传码
  6. 如何在行中统计满足条件的数据个数占比
  7. 【学习笔记】数字证书,私钥——公钥
  8. Mysql优化之使用短索引
  9. [Brute force][规律] Jzoj P3084 超级变变变
  10. Cisco Viptela SD-WAN 基本部署