数字图像处理学习笔记(1)---位图的读写、几何变换、傅里叶变换、直方图均衡

参考书:《Visual C++ 数字图象处理》谢凤英

位映象:二维的像素矩阵。

灰度图像的像素数据就是一个矩阵,矩阵的行对应图像的高(单位像素),矩阵的列对应图像的宽(单位像素)。

数字图像与图像矩阵

RGB彩色空间(有源物体):


任意彩色光L的配色公式:L=r(R)+g(G)+b(B)

CMY彩色空间(无源物体):

HIS彩色空间(色调、饱和度、强度)

色调:表示颜色(数量化为角度值,如红 0度)

饱和度:表示色的纯度,也就是彩色光中掺杂白光的程度。白光越多饱和度越低,白光越少饱和度越高且颜色越纯(数量化为百分数)。

强度:表示人眼感受彩色光的颜色的强弱程度,它与彩色光的能量大小有关。

       人的视觉系统对亮度的敏感程度远强于对颜色浓度的敏感程度。


HIS彩色空间模型

RGB彩色空间转换到HIS彩色空间公式:



BMP文件结构及其存取

BMP文件格式是一种将内存和显示器的图像数据不经过压缩直接存盘的文件格式,也称为位图文件。


第一部分位图文件头BITMAPFILEHEADER,是一个结构,其定义如下:

typedefstruct tagBITMAPFILEHEADER {

WORD          bfType;

DWORD      bfSize;

WORD          bfReserved1;

WORD          bfReserved2;

DWORD      bfOffBits;

}BITMAPFILEHEADER,FAR*LPBITMAPFILEHEADER,*PBITMAPFILEHEADER;

这个结构的长度是固定的,为14个字节(WORD为无符号16位整数,DWORD为无符号32位整数),各个域的说明如下:

bfType

指定文件类型,必须是0x424D,即字符串“BM”,也就是说所有*.bmp文件的头两个字节都是“BM”。

bfSize

指定文件大小,包括这14个字节。

bfReserved1,bfReserved2     

为保留字,不用考虑

bfOffBits

为从文件头到实际的位图数据的偏移字节数,即上图中前三个部分的长度之和。

 

第二部分为位图信息头BITMAPINFOHEADER,也是一个结构,定义如下:

typedefstruct tagBITMAPINFOHEADER{

DWORD      biSize;

LONG           biWidth;

LONG           biHeight;

WORD          biPlanes;

WORD          biBitCount

DWORD      biCompression;

DWORD      biSizeImage;

LONG           biXPelsPerMeter;

LONG           biYPelsPerMeter;

DWORD        biClrUsed;

DWORD      biClrImportant;

}BITMAPINFOHEADER,LAR*LPBITMAPINFOHEADER,*PBITMAPINFOHEADER;

这个结构的长度是固定的,为40个字节(LONG为32位整数),各个域的说明如下:

biSize

指定这个结构的长度,为40。

biWidth

指定图象的宽度,单位是象素。

biHeight

指定图象的高度,单位是象素。

biPlanes

目标设备的级别,必须是1。

biBitCount

每个像素所占的位数,常用的值为1(黑白二色图), 4(16色图), 8(256色), 24(真彩色图),新的BMP格式支持32位色。

biCompression

指定位图是否压缩,有效的值为BI_RGB(未经压缩),BI_RLE8,BI_RLE4,BI_BITFIELDS(都是一些Windows定义好的常量)。只讨论未压缩的情形,即biCompression=BI_RGB的情况。

biSizeImage

指定实际的位图数据占用的字节数,该值得大小在第四部分位图数据中有具体解释。

biXPelsPerMeter

指定目标设备的水平分辨率,单位是每米的象素个数。

biYPelsPerMeter

指定目标设备的垂直分辨率,单位同上。

biClrUsed

指定本图象实际用到的颜色数,如果该值为零,则用到的颜色数为2biBitCount

biClrImportant

指定本图象中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的。

 

第三部分颜色表(真彩色图,前面已经讲过,是不需要调色板的)BITMAPINFOHEADER后直接是位图数据。

调色板实际上是一个数组,共有biClrUsed个元素(如果该值为零,则有2biBitCount个元素)。数组中每个元素的类型是一个RGBQUAD结构,占4个字节,其定义如下:

typedefstruct tagRGBQUAD {

BYTE   rgbBlue; //该颜色的蓝色分量

BYTE   rgbGreen; //该颜色的绿色分量

BYTE   rgbRed; //该颜色的红色分量

BYTE   rgbReserved; //保留值

}RGBQUAD;

第四部分就是实际的图象数据了。对于用到调色板的位图,图象数据就是该象素颜在调色板中的索引值。对于真彩色图,图象数据就是实际的R、G、B值(三个分量的存储数据为B/G/R)。下面针对2色、16色、256色位图和真彩色位图分别介绍。

对于2色位图,用1位就可以表示该象素的颜色(一般0表示黑,1表示白),所以一个字节可以表示8个象素。

对于16色位图,用4位可以表示一个象素的颜色,所以一个字节可以表示2个象素。

对于256色位图,一个字节刚好可以表示1个象素。

对于真彩色图,三个字节才能表示1个象素,哇,好费空间呀!没办法,谁叫你想让图的颜色显得更亮丽呢,有得必有失嘛。

对于真彩色图,三个字节才能表示1个象素,哇,好费空间呀!没办法,谁叫你想让图的颜色显得更亮丽呢,有得必有失嘛。

要注意两点:

(1)     每一行的字节数必须是4的整倍数,如果不是,则需要补齐。这在前面介绍biSizeImage时已经提到了。一个扫描行的真实字节数计算公式:

DataSizePerLine=(biWidth*biBitCount/8+3)/4*4;

biSizeImage=DataSizePerLine*biHeight.

(2)    一般来说,BMP文件是从图像的左下角开始扫描图像,即从左往右,从下往上,将图像的像素值一一记录下来。图像的坐标零点为图像左下角。

 

BMP文件的读写


BMP文件读入流程

 

BMP文件写操作流程

在windows.h中定义了位图文件格式的结构

定义一个Bitmap类,具有位图读写、几何变换、傅里叶变换、直方图均衡操作。文件名bmp.h

#include<Windows.h>
//复数类
class ComplexNumber
{
public:
	float imag;//虚部
	float real;//实部
};

class Bitmap
{
private:
	BITMAPFILEHEADER fileHeader;
	BITMAPINFOHEADER infoHeader;	
public:
	int width_p, height_p, bitCount;//位图的宽与高(单位:像素),像素所占位数信息
	unsigned char* dataBuf;//指向位图图像数据的指针
	LPRGBQUAD colorTable;//指向位图图像颜色表的指针
public:
	Bitmap();
	~Bitmap();
	bool read(char* fileName);//读图像数据
	bool write(char* fileName);//写图像数据
	void translation(int offsetX, int offsetY);//平移变换
	//缩放变换,interpolationWay='n','l','c'
	void zoom(float ratioX, float rationY, char interpolationWay);
	void rotate(float angel);//旋转变换,单位度
	void fourier();//傅里叶变换
	int* computeHistGray();//直方图统计(针对灰度图像)
	int* computeHistBrightness();//亮度直方图统计(针对真彩色图像的亮度值)
	int* computeHistRed();//彩色图像的红色通道直方图统计
	int* computeHistGreen();//彩色图像的绿色通道直方图统计
	int* computeHistBlue();//彩色图像的蓝色通道直方图统计
	float computeHistAverage();//计算直方图的平均值
	float computeDeviation();//计算直方图的均方差
	void histEqualization();//直方图均衡、针对灰度图像(深度8位)
	void releasedHist(); //释放直方图统计数据的内存

private:
	void neighborInterpolation(float ratioX, float ratioY);//最邻近插值,插值函数用在缩放变换中
	void dbLinearInterpolatin(float ratioX, float ratioY);//双线性插值
	void cubicConvoInterpolatin(float ratioX, float ratioY);//立方卷积插值
	//2-D快速傅里叶变换
	void ImgFFT2D(unsigned char* imgBuf,unsigned char *imgBufOut,ComplexNumber* fftBuf);
	//1-D快速傅里叶变换
	void FFT1D(ComplexNumber* arrayBuf, int n);
};





posted @ 2014-12-07 21:31  corfox  阅读(587)  评论(0编辑  收藏  举报