图像增强——Roberts算子、Sobel算子、Prewitt算子、Laplace算子

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

#include
#include"bmp.h"
#include "stdlib.h"
#include "math.h"
#include "time.h"
#include 
#include
using namespace std;

#define PI 3.14159
#define LENGTH_NAME_BMP 30//文件名长度

#define U 0//高斯分布的均值
#define D 0//高斯分布的均方差
FILE *fpi, *fpw;
BITMAPFILEHEADER strHead;
RGBQUAD strPla[256];
BITMAPINFOHEADER strInfo;

int Roberts1[4] = { -1,0,0,1 };
int Roberts2[4] = { 0,-1,1,0 };
int Sobel1[9] = { -1,-2,-1,0,0,0,1,2,1 };
int Sobel2[9] = { -1,0,1,-2,0,2,-1,0,1 };
int Prewitt1[9] = { -1,-1,-1,0,0,0,1,1,1 };
int Prewitt2[9] = { -1,0,1,-1,0,1,-1,0,1 };
int Laplace1[9] = { 0,1,0,1,-4,1,0,1,0 };
int Laplace2[9] = { 1,1,1,1,-8,1,1,1,1 };

//显示位图文件头信息
void showBmpHead(BITMAPFILEHEADER pBmpHead)
{
	cout << "位图文件头" << endl;
	cout << "文件大小" << pBmpHead.bfSize << endl;
	cout << "保留字_1" << pBmpHead.bfReserved1 << endl;
	cout << "保留字_2" << pBmpHead.bfReserved2 << endl;
	cout << "实际位图数据的偏移字节数:" << pBmpHead.bf0ffBits << endl;
}

void showBmpInforHead(tagBITMAPINFOHEADER pBmpInforHead)
{
	cout << "位图信息头" << endl;
	cout << "结构体的长度" << pBmpInforHead.biSize << endl;
	cout << "位图宽:" << pBmpInforHead.biWidth << endl;
	cout << "位图高:" << pBmpInforHead.biHeight << endl;
	cout << "biPlanes平面数:" << pBmpInforHead.biPlanes << endl;
	cout << "biBitCount采用颜色位数" << pBmpInforHead.biBitCount << endl;
	cout << "压缩方式" << pBmpInforHead.biCompression << endl;
	cout << "biSizeImage实际位图数据占用的字节数" << pBmpInforHead.biSizeImage << endl;
	cout << "X方向分辨率:" << pBmpInforHead.biXPelsPerMeter << endl;
	cout << "Y方向分辨率:" << pBmpInforHead.biYPelsPerMeter << endl;
	cout << "使用的颜色数:" << pBmpInforHead.biClrUsed << endl;
	cout << "重要颜色数:" << pBmpInforHead.biClrImportant << endl;
}

int main()
{
	int Gaus_S();
	void conv2(IMAGEDATA *filter, int arr1[], int arr2[], int res[], int filterW, int filterH, int arrW, int arrH);
	void RobertsMethod(IMAGEDATA *filter, int filterW, int filterH);
	void Laplace(IMAGEDATA *filter, int filterW, int filterH);

	char strFile[LENGTH_NAME_BMP];//bmp文件名
	IMAGEDATA *imagedata = NULL;//动态分配存储原图片的像素信息的二维数组
	IMAGEDATA *imagedataRot = NULL;//动态分配处理后的图片像素信息
	int width, height;//图片的宽度和高度
	cout << "请输入所要读取的文件名(末尾要带有.bmp):" << endl;
	cin >> strFile;
	
	fopen_s(&fpi,strFile,"rb");

	//读取bmp图片信息、初始化数组
	if (fpi != NULL)
	{
		WORD bfType;
		fread(&bfType, 1, sizeof(WORD), fpi);
		if (0x4d42 != bfType)
		{
			cout << "the file is not a bmp file!" << endl;
			return NULL;
		}
		//读取bmp文件的文件头和信息头
		fread(&strHead, 1, sizeof(tagBITMAPFILEHEADER), fpi);
		showBmpHead(strHead);
		
		fread(&strInfo, 1, sizeof(tagBITMAPINFOHEADER), fpi);
		showBmpInforHead(strInfo);

		for (unsigned int nCounti = 0; nCounti < strInfo.biClrUsed; nCounti++)
		{
			fread((char *)&strPla[nCounti].rgbBlue, 1, sizeof(BYTE), fpi);
			fread((char *)&strPla[nCounti].rgbGreen, 1, sizeof(BYTE), fpi);
			fread((char *)&strPla[nCounti].rgbRed, 1, sizeof(BYTE), fpi);
			cout << "strPla[nCounti].rgbBlue" << strPla[nCounti].rgbBlue << endl;
			cout << "strPla[nCounti].rgbGreen" << strPla[nCounti].rgbGreen << endl;
			cout << "strPla[nCounti].rgbRed" << strPla[nCounti].rgbRed << endl;
		}
	
		width = strInfo.biWidth;
		height = strInfo.biHeight;
		imagedata = (IMAGEDATA *)malloc(width*height*sizeof(IMAGEDATA));
		//初始化原始图片的像素数组
		for (int i = 0; i < height; ++i)
		{
			for (int j = 0; j < width; ++j)
			{
				(*(imagedata + i*width + j)).blue = 0;
				(*(imagedata + i*width + j)).green = 0;
				(*(imagedata + i*width + j)).red = 0;
			}
		}

	
		fread(imagedata, sizeof(struct tagIMAGEDATA)*width, height, fpi);
		fclose(fpi);
		
		//加入高斯噪声
		int x, y, p;
		srand((unsigned)time(NULL));
		for (y = 0; y < height; y++)
		{
			for (x = 0; x < width; x++)
			{
				(*(imagedata + y*width + x)).blue += Gaus_S();
				(*(imagedata + y*width + x)).green += Gaus_S();
				(*(imagedata + y*width + x)).red += Gaus_S();
			}
		}
		//Roberts算子
		int method;
		cout << "选择Roberts算子请输入1,Sobel算子请输入2,Prewitt算子请输入3,Laplace算子请输入4:" << endl;
		cin >> method;
		switch (method)
		{
		case 1:
			RobertsMethod(imagedata, width, height);
			break;
		case 2:
			int res1[25];
			for (y = 1; y < height - 2; y++)
			{
				for (x = 1; x < width - 2; x++)
				{
					conv2(imagedata + y*width + x, Sobel1, Sobel2, res1, 3, 3, 3, 3);
				}
			}
			break;
		case 3:
			int res2[25];
			for (y = 1; y < height - 2; y++)
			{
				for (x = 1; x < width - 2; x++)
				{
					conv2(imagedata + y*width + x, Prewitt1, Prewitt2, res2, 3, 3, 3, 3);
				}
			}
			break;
		case 4:
			int res3[25];
			for (y = 1; y < height - 2; y++)
			{
				for (x = 1; x < width - 2; x++)
				{
					conv2(imagedata + y*width + x, Laplace1, Laplace2, res3, 3, 3, 3, 3);
				}
			}
			break;
		default:
			cout << "输入错误" << endl;
		}

	}
	else
	{
		cout << "file open error" << endl;
		system("pause");
		return NULL;
	}
	
	
	//保存bmp图片
	cout << "保存的文件名(必须在文件名后输入.bmp):" << endl;
	char s[LENGTH_NAME_BMP];
	cin >> s;
	if (fopen_s(&fpw, s, "wb") != NULL)
	{
		cout << "create the bmp file error!" << endl;
		system("pause");
		return NULL;
	}
	WORD bfType_w = 0x4d42;
	fwrite(&bfType_w, 1, sizeof(WORD), fpw);
	fwrite(&strHead, 1, sizeof(tagBITMAPFILEHEADER), fpw);
	strInfo.biWidth =  width;
	strInfo.biHeight =  height;
	fwrite(&strInfo, 1, sizeof(tagBITMAPINFOHEADER), fpw);
	//保存调色板数据
	for (unsigned int nCounti = 0; nCounti < strInfo.biClrUsed; nCounti++)
	{
		fwrite(&strPla[nCounti].rgbBlue, 1, sizeof(BYTE), fpw);
		fwrite(&strPla[nCounti].rgbGreen, 1, sizeof(BYTE), fpw);
		fwrite(&strPla[nCounti].rgbRed, 1, sizeof(BYTE), fpw);
	}
	//保存像素数据
	for (int i = 0; i < height; ++i)
	{
		for (int j = 0; j <  width; j++)
		{
			fwrite(&(*(imagedata + i * width + j)).red, 1, sizeof(BYTE), fpw);
			fwrite(&(*(imagedata + i * width + j)).green, 1, sizeof(BYTE), fpw);
			fwrite(&(*(imagedata + i * width + j)).blue, 1, sizeof(BYTE), fpw);
		}
	}
	fclose(fpw);

	//释放内存
	delete[] imagedata;

	system("pause");
	return 0;
	
}

//产生高斯样本,以U为均值,D为均方差
int Gaus_S() {
	double sum = 0;
	for (int i = 0; i < 12; i++)
		sum += rand() / 32767.00;
	return int(U + D*(sum - 6));
}

//卷积计算
void conv2(IMAGEDATA *filter, int arr1[],int arr2[],int res[],int filterW,int filterH, int arrW, int arrH)
{
	int temp1;
	int temp2;
	int i = 0, j = 0;
	//blue
	for (; i < filterH+arrH-1; i++)
	{
		for (; j = 0 && (i - m) < arrH && (j - n) >= 0 && (j - n) < arrW)
					{
						temp1 += (*(filter+m*filterW+n)).blue*arr1[(i - m)*arrW+j-n];
						temp2 += (*(filter + m*filterW + n)).blue*arr2[(i - m)*arrW+j-n];
					}
				}
			}
			res[i*filterW+j]= (temp1^2+temp2^2)^(1/2);
		}
	}
	(*(filter)).blue = res[((i-1)/2)*filterW+(j-1)/2];

	//red
	for (i=0; i < filterH + arrH - 1; i++)
	{
		for (j=0; j = 0 && (i - m) < arrH && (j - n) >= 0 && (j - n) < arrW)
					{
						temp1 += (*(filter + m*filterW + n)).red*arr1[(i - m)*arrW + j - n];
						temp2 += (*(filter + m*filterW + n)).red*arr2[(i - m)*arrW + j - n];
					}
				}
			}
			res[i*filterW + j] = (temp1 ^ 2 + temp2 ^ 2)^(1/2);
		}
	}
	(*(filter)).red = res[((i - 1) / 2)*filterW + (j - 1) / 2];
	//green
	for (i = 0; i < filterH + arrH - 1; i++)
	{
		for (j = 0; j = 0 && (i - m) < arrH && (j - n) >= 0 && (j - n) < arrW)
					{
						temp1 += (*(filter + m*filterW + n)).green*arr1[(i - m)*arrW + j - n];
						temp2 += (*(filter + m*filterW + n)).green*arr2[(i - m)*arrW + j - n];
					}
				}
			}
			res[i*filterW + j] = (temp1 ^ 2 + temp2 ^ 2)^(1/2);
		}
	}
	(*(filter)).green = res[((i - 1) / 2)*filterW + (j - 1) / 2];
}
//Roberts算子计算函数
void RobertsMethod(IMAGEDATA *filter,int filterW,int filterH)
{
	for (int m = 1; m < filterH-2; m++)
		for (int n = 1; n < filterW-2; n++)
		{
			(*(filter + m*filterW + n)).blue = (((*(filter + m*filterW + n)).blue - (*(filter + (m + 1)*filterW + n + 1)).blue) ^ 2 + ((*(filter + m*filterW + n + 1)).blue - (*(filter + (m + 1)*filterW + n)).blue)) ^ (1 / 2);
		
			(*(filter + m*filterW + n)).green = (((*(filter + m*filterW + n)).green - (*(filter + (m + 1)*filterW + n + 1)).green) ^ 2 + ((*(filter + m*filterW + n + 1)).green - (*(filter + (m + 1)*filterW + n)).green)) ^ (1 / 2);
		
			(*(filter + m*filterW + n)).red = (((*(filter + m*filterW + n)).red - (*(filter + (m + 1)*filterW + n + 1)).red) ^ 2 + ((*(filter + m*filterW + n + 1)).red - (*(filter + (m + 1)*filterW + n)).red)) ^ (1 / 2);
		
}
}

 

你可能感兴趣的:(C++)