1. 程式人生 > >影象資訊處理實驗二

影象資訊處理實驗二

要求:

1. Image binarization
2. Binary image erosion
3. Binary image delation
4. Binary image opening
5. Binary image closing

#include <stdio.h>
#include <Windows.h>


void ToRGB(char* a, char* b)
{
	BITMAPFILEHEADER fileHeader;// 點陣圖檔案頭
	BITMAPINFOHEADER infoHeader;// 點陣圖資訊頭
	FILE* pFile = fopen(a, "rb");
	if (pFile == NULL)
	{
		printf("開啟點陣圖失敗\n");
		exit(-1);
	}

	fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile);  //讀取檔案頭
	fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile);  //讀取資訊頭
	WORD bitCount = infoHeader.biBitCount;  //顏色位數
	if (bitCount == 16)
	{
		exit(-1);
	}
	int Clr = 0;

	RGBQUAD *QUAD = NULL;
	if (bitCount < 16)
	{

		Clr = infoHeader.biClrUsed ? infoHeader.biClrUsed : 1 << bitCount;
		if (Clr>256)
			Clr = 0;
	}
	// 讀取調色盤
	int i = 0, j = 0;
	if (Clr > 0)
	{
		QUAD = (RGBQUAD*)malloc(sizeof(RGBQUAD)*Clr);
		fread(QUAD, sizeof(RGBQUAD)*Clr, 1, pFile);
		for (i = 0; i < Clr; i++)
		{
			QUAD[i].rgbRed = QUAD[i].rgbBlue = QUAD[i].rgbGreen =
				(BYTE)(0.3 * QUAD[i].rgbRed + 0.59 * QUAD[i].rgbGreen + 0.11 * QUAD[i].rgbBlue);
		}
	}
	LONG pW = infoHeader.biWidth;     //影象資料的寬度
	LONG pH = infoHeader.biHeight;    //影象資料的高度

    int pSize = ((pW * bitCount)>>3)*pH;  //影象資料大小
	BYTE* P = (BYTE*)malloc(pSize);   //申請空間儲存影象資料
	int LineSize = ((pW * bitCount)>> 3);  //行資料大小
	fread(P, pSize, 1, pFile);     //存入影象資料
	if (Clr == 0)
	{
		for (i = 0; i < pH; i++)//行
		{
			if (bitCount == 24)
			{
				for (j = 0; j < pW * 3; j = j + 3)// 列,因為每個畫素佔3個位元組
                {
					int n = i*LineSize + j;
					int r = P[n];
					int g = P[n+1];
					int b = P[n + 2];

					int y = 0.299*r + 0.587*g + 0.114*b;
					int u = 0.492*(b - y);
					int v = 0.877*(r - y);
					y = y + 31;  //把所有畫素點的y增大31
					/*if (y > 255)  //如果越界則置為255
						y = 255;
					if (y < 0)
						y = 0;
					if (u > 255)  //如果越界則置為255
						u = 255;
					if (u < 0)
						u = 0;
					if (v > 255)  //如果越界則置為255
						v = 255;
					if (v < 0)
						v = 0; */
					int R = y + 1.14*v;
					int G = y -0.394*u - 0.581*v;
					int B = y + 2.032*u;

					if (R > 255)  //R如果越界則置為255
						R = 255;
					if (R < 0)
						R = 0;
					if (G > 255)  //如果越界則置為255
						G = 255;
					if (G < 0)
						G = 0;
					if (B > 255)  //如果越界則置為255
						B = 255;
					if (B < 0)
						B = 0;
					P[n]  = (BYTE)(R); //分別是新r.g.b分量
					P[n + 1] = (BYTE)(G);
					P[n + 2] = (BYTE)(B);
				}
			}

		}
	}
	FILE* dFile = fopen(b, "wb");//建立目標檔案

	fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile);   //寫入檔案頭

	fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile);  //寫入檔案資訊頭
	if (QUAD)
	{
		fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile);
	}
	//寫入影象資料
	fwrite(P, pSize, 1, dFile);
	fclose(dFile);

	if (QUAD)
	{
		free(QUAD);
		QUAD = NULL;
	}
	if (P)
	{
		free(P);
		P=NULL;
	}
}

void ToGrey(char* a, char* b)
{
	BITMAPFILEHEADER fileHeader;// 點陣圖標頭檔案
	BITMAPINFOHEADER infoHeader;// 點陣圖資訊頭
	FILE* pFile = fopen(a, "rb");
	if (pFile == NULL)
	{
		printf("開啟檔案失敗\n");
		exit(-1);
	}
	// 讀取頭資訊
	fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile);   //讀取檔案頭
	fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile);   //讀取資訊頭
	WORD bitCount = infoHeader.biBitCount;//色彩的位數
	if (bitCount == 16)
	{
		exit(-1);
	}
	int Clr = 0;

	RGBQUAD *QUAD = NULL;
	if (bitCount < 16)
	{

		Clr = infoHeader.biClrUsed ? infoHeader.biClrUsed : 1 << bitCount;
		if (Clr>256)
			Clr = 0;
	}
	// 讀取調色盤
	int i = 0, j = 0;
	if (Clr > 0)
	{
		QUAD = (RGBQUAD*)malloc(sizeof(RGBQUAD)*Clr);
		fread(QUAD, sizeof(RGBQUAD)*Clr, 1, pFile);
		for (i = 0; i < Clr; i++)
		{
			QUAD[i].rgbRed = QUAD[i].rgbBlue = QUAD[i].rgbGreen =
				(BYTE)(0.3 * QUAD[i].rgbRed + 0.59 * QUAD[i].rgbGreen + 0.11 * QUAD[i].rgbBlue);  //灰度影象三個都是y
		}
	}
	LONG pW = infoHeader.biWidth;     //影象資料的寬度
	LONG pH = infoHeader.biHeight;    //影象資料的高度

	int pSize = ((pW * bitCount)>>3)*pH;  //影象資料大小
	BYTE* P = (BYTE*)malloc(pSize);   //申請空間儲存影象資料
	int LineSize = ((pW * bitCount)>> 3);  //行資料大小
	fread(P, pSize, 1, pFile);     //存入影象資料

    for(i = 0; i < pH; i++)//行
    {


			for (j = 0; j < pW*3; j = j + 3)// 列
			{
                int n = i*LineSize + j;
                if(0.299*P[n] + 0.587*P[n + 1] + 0.114*P[n + 2]>120)
                    P[n] = P[n + 1] = P[n + 2] = (BYTE)255;
                else
                    P[n] = P[n + 1] = P[n + 2] = (BYTE)0;

			}


	}

	FILE* dFile = fopen(b, "wb");//建立目標檔案

	fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile);   //寫入檔案頭

	fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile);  //寫入檔案資訊頭
	if (QUAD)
	{
		fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile);
	}
	//寫入影象資料
	fwrite(P, pSize, 1, dFile);
	fclose(dFile);

	if (QUAD)
	{
		free(QUAD);
		QUAD = NULL;
	}
	if (P)
	{
		free(P);
		P = NULL;
	}
}

void Delation(char* a, char* b)
{
	BITMAPFILEHEADER fileHeader;// 點陣圖標頭檔案
	BITMAPINFOHEADER infoHeader;// 點陣圖資訊頭
	FILE* pFile = fopen(a, "rb");
	if (pFile == NULL)
	{
		printf("開啟檔案失敗\n");
		exit(-1);
	}
	// 讀取頭資訊
	fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile);   //讀取檔案頭
	fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile);   //讀取資訊頭
	WORD bitCount = infoHeader.biBitCount;//色彩的位數

	int Clr = 0;

	RGBQUAD *QUAD = NULL;

	int i = 0, j = 0;
	LONG pW = infoHeader.biWidth;     //影象資料的寬度
	LONG pH = infoHeader.biHeight;    //影象資料的高度

	int pSize = ((pW * bitCount)>>3)*pH;  //影象資料大小
	BYTE* P = (BYTE*)malloc(pSize);   //申請空間儲存影象資料
	int LineSize = ((pW * bitCount)>> 3);  //行資料大小
	fread(P, pSize, 1, pFile);     //存入影象資料

    //先二值化
    for(i = 0; i < pH; i++)//行
    {
		for (j = 0; j < pW*3; j = j + 3)// 列
		{
            int n = i*LineSize + j;
            if(0.299*P[n] + 0.587*P[n + 1] + 0.114*P[n + 2]>120)
                P[n] = P[n + 1] = P[n + 2] = (BYTE)255;
            else
                P[n] = P[n + 1] = P[n + 2] = (BYTE)0;


		}
	}
    //再delation
    int width=3,height=3;
    int mid=(width+1)/2-1;
    int p,q;
    int n;
    BYTE v = 255;
    for(i = mid; i < pH - mid; i++)//行
    {
        for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列
		{
		    for(p = 0; p < height; p++)
            {
                for(q = 0; q < width * 3; q = q + 3)
                {
                    if(p == mid && q == mid) continue;
                    n=(i+p)*LineSize + (j+q);
                    v &= P[n];
                }
		    }
		    n = i * LineSize + j;
		    P[n] = P[n + 1] = P[n + 2] = v;
		    v = 255;
		}
	}

	FILE* dFile = fopen(b, "wb");//建立目標檔案

	fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile);   //寫入檔案頭

	fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile);  //寫入檔案資訊頭
	if (QUAD)
	{
		fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile);
	}
	//寫入影象資料
	fwrite(P, pSize, 1, dFile);
	fclose(dFile);

	if (QUAD)
	{
		free(QUAD);
		QUAD = NULL;
	}
	if (P)
	{
		free(P);
		P = NULL;
	}
}

void Erosion(char* a, char* b)
{
	BITMAPFILEHEADER fileHeader;// 點陣圖標頭檔案
	BITMAPINFOHEADER infoHeader;// 點陣圖資訊頭
	FILE* pFile = fopen(a, "rb");

	// 讀取頭資訊
	fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile);   //讀取檔案頭
	fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile);   //讀取資訊頭
	WORD bitCount = infoHeader.biBitCount;//色彩的位數

	int Clr = 0;

	RGBQUAD *QUAD = NULL;

	int i = 0, j = 0;

	LONG pW = infoHeader.biWidth;     //影象資料的寬度
	LONG pH = infoHeader.biHeight;    //影象資料的高度

	int pSize = ((pW * bitCount)>>3)*pH;  //影象資料大小
	BYTE* P = (BYTE*)malloc(pSize);   //申請空間儲存影象資料
	int LineSize = ((pW * bitCount)>> 3);  //行資料大小
	fread(P, pSize, 1, pFile);     //存入影象資料

    //先二值化
    for(i = 0; i < pH; i++)//行
    {
		for (j = 0; j < pW*3; j = j + 3)// 列
		{
            int n = i*LineSize + j;
            if(0.299*P[n] + 0.587*P[n + 1] + 0.114*P[n + 2]>120)
                P[n] = P[n + 1] = P[n + 2] = (BYTE)255;
            else
                P[n] = P[n + 1] = P[n + 2] = (BYTE)0;


		}
	}
    //再erosion
    int width=3,height=3;
    int mid=(width+1)/2-1;
    int p,q;
    int n;
    BYTE v = 0;
    for(i = mid; i < pH - mid; i++)//行
    {
        for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列
		{
		    for(p = 0; p < height; p++)
            {
                for(q = 0; q < width * 3; q = q + 3)
                {
                    if(p == mid && q == mid) continue;
                    n=(i+p)*LineSize + (j+q);
                    v |= P[n];
                }
		    }
		    n = i * LineSize + j;
		    P[n] = P[n + 1] = P[n + 2] = v;
		    v = 0;
		}
	}

	FILE* dFile = fopen(b, "wb");//建立目標檔案

	fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile);   //寫入檔案頭

	fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile);  //寫入檔案資訊頭
	if (QUAD)
	{
		fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile);
	}
	//寫入影象資料
	fwrite(P, pSize, 1, dFile);
	fclose(dFile);

	if (QUAD)
	{
		free(QUAD);
		QUAD = NULL;
	}
	if (P)
	{
		free(P);
		P = NULL;
	}
}

void Opening(char* a, char* b)
{
	BITMAPFILEHEADER fileHeader;// 點陣圖標頭檔案
	BITMAPINFOHEADER infoHeader;// 點陣圖資訊頭
	FILE* pFile = fopen(a, "rb");

	// 讀取頭資訊
	fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile);   //讀取檔案頭
	fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile);   //讀取資訊頭
	WORD bitCount = infoHeader.biBitCount;//色彩的位數

	int Clr = 0;

	RGBQUAD *QUAD = NULL;

	int i = 0, j = 0;

	LONG pW = infoHeader.biWidth;     //影象資料的寬度
	LONG pH = infoHeader.biHeight;    //影象資料的高度

	int pSize = ((pW * bitCount)>>3)*pH;  //影象資料大小
	BYTE* P = (BYTE*)malloc(pSize);   //申請空間儲存影象資料
	int LineSize = ((pW * bitCount)>> 3);  //行資料大小
	fread(P, pSize, 1, pFile);     //存入影象資料

    //先二值化
    for(i = 0; i < pH; i++)//行
    {
		for (j = 0; j < pW*3; j = j + 3)// 列
		{
            int n = i*LineSize + j;
            if(0.299*P[n] + 0.587*P[n + 1] + 0.114*P[n + 2]>120)
                P[n] = P[n + 1] = P[n + 2] = (BYTE)255;
            else
                P[n] = P[n + 1] = P[n + 2] = (BYTE)0;


		}
	}
    //再erosion
    int width=3,height=3;
    int mid=(width+1)/2-1;
    int p,q;
    int n;
    BYTE v = 0;
    for(i = mid; i < pH - mid; i++)//行
    {
        for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列
		{
		    for(p = 0; p < height; p++)
            {
                for(q = 0; q < width * 3; q = q + 3)
                {
                    if(p == mid && q == mid) continue;
                    n=(i+p)*LineSize + (j+q);
                    v |= P[n];
                }
		    }
		    n = i * LineSize + j;
		    P[n] = P[n + 1] = P[n + 2] = v;
		    v = 0;
		}
	}
    //再Delation
    v = 255;
    for(i = mid; i < pH - mid; i++)//行
    {
        for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列
		{
		    for(p = 0; p < height; p++)
            {
                for(q = 0; q < width * 3; q = q + 3)
                {
                    if(p == mid && q == mid) continue;
                    n=(i+p)*LineSize + (j+q);
                    v &= P[n];
                }
		    }
		    n = i * LineSize + j;
		    P[n] = P[n + 1] = P[n + 2] = v;
		    v = 255;
		}
	}

	FILE* dFile = fopen(b, "wb");//建立目標檔案

	fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile);   //寫入檔案頭

	fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile);  //寫入檔案資訊頭
	if (QUAD)
	{
		fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile);
	}
	//寫入影象資料
	fwrite(P, pSize, 1, dFile);
	fclose(dFile);

	if (QUAD)
	{
		free(QUAD);
		QUAD = NULL;
	}
	if (P)
	{
		free(P);
		P = NULL;
	}
}

void Closing(char* a, char* b)
{
	BITMAPFILEHEADER fileHeader;// 點陣圖標頭檔案
	BITMAPINFOHEADER infoHeader;// 點陣圖資訊頭
	FILE* pFile = fopen(a, "rb");

	// 讀取頭資訊
	fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile);   //讀取檔案頭
	fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile);   //讀取資訊頭
	WORD bitCount = infoHeader.biBitCount;//色彩的位數

	int Clr = 0;

	RGBQUAD *QUAD = NULL;

	int i = 0, j = 0;

	LONG pW = infoHeader.biWidth;     //影象資料的寬度
	LONG pH = infoHeader.biHeight;    //影象資料的高度

	int pSize = ((pW * bitCount)>>3)*pH;  //影象資料大小
	BYTE* P = (BYTE*)malloc(pSize);   //申請空間儲存影象資料
	int LineSize = ((pW * bitCount)>> 3);  //行資料大小
	fread(P, pSize, 1, pFile);     //存入影象資料

    //先二值化
    for(i = 0; i < pH; i++)//行
    {
		for (j = 0; j < pW*3; j = j + 3)// 列
		{
            int n = i*LineSize + j;
            if(0.299*P[n] + 0.587*P[n + 1] + 0.114*P[n + 2]>120)
                P[n] = P[n + 1] = P[n + 2] = (BYTE)255;
            else
                P[n] = P[n + 1] = P[n + 2] = (BYTE)0;


		}
	}
	//先Delation
	int width=3,height=3;
    int mid=(width+1)/2-1;
    int p,q;
    int n;
	BYTE v = 255;
    for(i = mid; i < pH - mid; i++)//行
    {
        for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列
		{
		    for(p = 0; p < height; p++)
            {
                for(q = 0; q < width * 3; q = q + 3)
                {
                    if(p == mid && q == mid) continue;
                    n=(i+p)*LineSize + (j+q);
                    v &= P[n];
                }
		    }
		    n = i * LineSize + j;
		    P[n] = P[n + 1] = P[n + 2] = v;
		    v = 255;
		}
	}
    //再erosion

    v = 0;
    for(i = mid; i < pH - mid; i++)//行
    {
        for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列
		{
		    for(p = 0; p < height; p++)
            {
                for(q = 0; q < width * 3; q = q + 3)
                {
                    if(p == mid && q == mid) continue;
                    n=(i+p)*LineSize + (j+q);
                    v |= P[n];
                }
		    }
		    n = i * LineSize + j;
		    P[n] = P[n + 1] = P[n + 2] = v;
		    v = 0;
		}
	}

	FILE* dFile = fopen(b, "wb");//建立目標檔案

	fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile);   //寫入檔案頭

	fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile);  //寫入檔案資訊頭
	if (QUAD)
	{
		fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile);
	}
	//寫入影象資料
	fwrite(P, pSize, 1, dFile);
	fclose(dFile);

	if (QUAD)
	{
		free(QUAD);
		QUAD = NULL;
	}
	if (P)
	{
		free(P);
		P = NULL;
	}
}


int main()
{

	ToGrey("d.bmp", "grayd.bmp");
	ToRGB("d.bmp", "rgbd.bmp");
	Erosion("d.bmp", "erosiond.bmp");
	Delation("d.bmp","delationd.bmp");
	Opening("d.bmp","opend.bmp");
	Closing("d.bmp","closed.bmp");
	return 0;
}