1.图像文件格式及特点
(1)矢量图
存储画图指令,优势是缩放不会拉伸变形,但很难获得,应用受限。
(2)位图 Bitmap
通过光栅化获得,优势是容易获得,缺点是容易出现模糊/走样现象。
光栅化:将几何图形转换为像素网格表示
①GIF
八位索引图(每通道8bit),每个像素存储一个索引值0-255,一共256种颜色;
具有抖动特性;具有动画和透明特性;
抖动:像素索引位数较少时,可以混合两个颜色产生另一个颜色
动画:多帧
透明:不遮盖
②JPEG
16位索引图,无需抖动,适合颜色丰富的图片;
能一次存储大量图片;
有损压缩,可能造成边缘模糊和像素值改变;
假设一张JPEG图片,为RGB三通道,那么颜色种类一共有:2^16*2^16*2^16种,颜色丰富
③PNG
无损压缩, 基于zip压缩算法,适用于视觉处理中间结果;
可以存储半透明图像,多一个透明度通道alpha(0完全透明-1完全不透明,非必要);
④BMP
无压缩,占用存储空间大;
可以编制索引,适用于颜色较少时,类似于GIF;可以不编制索引,直接存储BGR,适用于颜色较多时;
分为DIB(设备无关位图)/DDB(设备相关位图);
默认存储BGR而非常规的RGB;
2.图像在逻辑上的表示/内存数据格式:
逻辑表示:基于像素pixel 空间(x,y)+颜色(R,G,B)/灰度值
内存数据格式:和前面介绍的图像文件格式一样,包括矢量图和位图。
几个重要概念:
像素深度:存储每个像素所用的位数;
图像深度:存储每个像素颜色所用的位数,也叫色深;
所以,像素深度=图像深度+描述其他属性(如透明度)所用的位数,即像素深度>=图像深度;
位深:像素每个通道的位数;
注意区分:
像素深度和图像深度都是描述像素的,而位深是描述通道的,每个像素可能有一个或多个通道;
假如色深为8,那么颜色种类有2^8种;假如位深为8,且为3通道,那么颜色种类有2^8*2^8*2^8种。
3.程序访问图像的数据
//Scan Pixels in ROI
void scan_roi_pixels(MyImage &img,int x,int y,int roi_width,int roi_height)
{
scan_pixels(get_pixel(img,x,y),roi_width,roi_height,img.step,img.nc());
//img.step:每行字节数 img.nc()通道数
}
//Scan Pixels
void scan_pixels(uchar *data,int width,int height,int step,int nc)
{
uchar *row=data;
for(int yi=0;yi<height;++yi,row+=step)
{
uchar *px=row;
for(int xi=0;xi<width;++xi,px+=nc)
{
//address pixel(xi,yi)
}
}
}
//Get Pixel
//img.type=CV_8UC3:8位无符号,3通道
uchar* get_pixel(const MyImage &img,int x,int y)
{
return (uchar*) img.data+y*img.step+x*3;
}
//img.type=CV_32SC3:32位带符号,3通道
int* get_pixel(const MyImage &img,int x,int y)
{
return (int*)(char*)img.data+y*img.step+x*3*4;
}
//若为8*n位 return img.data+y*img.width*nc*n+x*nc*n; 若图像有其他填充,这样写不对。