简单识别BMP图像里物体

 .h

typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef long LONG;
//位图文件头定义;   
//其中不包含文件类型信息(由于结构体的内存结构决定,   
//要是加了的话将不能正确读取文件信息)   
typedef struct  tagBITMAPFILEHEADER {
	//WORD bfType;//文件类型,必须是0x4d42,即字符“BM”   
	DWORD bfSize;//文件大小   
	WORD bfReserved1;//保留字   
	WORD bfReserved2;//保留字   
	DWORD bfOffBits;//从文件头到实际位图数据的偏移字节数   
}BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER {
	DWORD biSize;//信息头大小   
	LONG biWidth;//图像宽度   
	LONG biHeight;//图像高度   
	WORD biPlanes;//位平面数,必须为1   
	WORD biBitCount;//每像素位数   
	DWORD  biCompression; //压缩类型   
	DWORD  biSizeImage; //压缩图像大小字节数   
	LONG  biXPelsPerMeter; //水平分辨率   
	LONG  biYPelsPerMeter; //垂直分辨率   
	DWORD  biClrUsed; //位图实际用到的色彩数   
	DWORD  biClrImportant; //本位图中重要的色彩数   
}BITMAPINFOHEADER; //位图信息头定义   

typedef struct tagRGBQUAD {
	BYTE rgbBlue; //该颜色的蓝色分量   
	BYTE rgbGreen; //该颜色的绿色分量   
	BYTE rgbRed; //该颜色的红色分量   
	BYTE rgbReserved; //保留值   
}RGBQUAD;//调色板定义   

//像素信息   
typedef struct tagIMAGEDATA
{
	BYTE red;
	BYTE green;
	BYTE blue;
}IMAGEDATA;

.cpp 

#include "ReadBmp.h"
#include <stdio.h>     
#include <stdlib.h>   
#include <iostream> 
#include <opencv2\opencv.hpp>
#define INF 65535
using namespace cv;
using namespace std;
//变量定义   
BITMAPFILEHEADER strHead;
RGBQUAD strPla[256];//256色调色板   
BITMAPINFOHEADER strInfo;   
//显示位图文件头信息   
int nx[4] = { 0,1,0,-1 };
int ny[4] = { 1,0,-1,0 };
int minx = INF;
int miny = INF;
int maxx = 0;
int maxy = 0;
int wi;
int hi;

void dfs(int (&grid)[256][256], int x, int y) {
	int n = wi;
	int m = hi;
	if (x < 0 || x >= n || y < 0 || y >= m || (grid[x][y] == 0) || (grid[x][y] == 2)) {
		return;
	}
	//cout << x << " " << y << endl;
	grid[x][y] = 2;
	minx = min(minx, x);
	miny = min(miny, y);
	maxx = max(maxx, x);
	maxy = max(maxy, y);
	for (int i = 0; i < 4; i++) {
		int xn = x + nx[i];
		int yn = y + ny[i];
		dfs(grid, xn, yn);
	}
	return;
}

void showBmpHead(BITMAPFILEHEADER pBmpHead) {
	cout << "位图文件头" << endl <<endl;
	//cout<<"bfType value is "<<hex<<pBmpHead.bfType<<endl;   
	cout << "文件大小:" << pBmpHead.bfSize << endl;
	cout << "保留字_1:" << pBmpHead.bfReserved1 << endl;
	cout << "保留字_2:" << pBmpHead.bfReserved2 << endl;
	cout << "实际位图数据的偏移字节数:" << pBmpHead.bfOffBits << endl << endl;
}

void showBmpInforHead(tagBITMAPINFOHEADER pBmpInforHead) {
	cout << "位图信息头" << endl << 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;
	wi = pBmpInforHead.biWidth;
	hi = pBmpInforHead.biHeight;
}

tagRGBQUAD* ReadFile(char *strFile) {
	FILE *fpi;
	int i;
	fpi = fopen(strFile, "rb");
	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);//显示文件信息头   

		//读出图片的像素数据   
		cout << endl;
		IMAGEDATA **imagedata;//存储像素信息
		imagedata = (IMAGEDATA **)malloc(sizeof(IMAGEDATA*)*strInfo.biHeight);
		for (i = 0; i < strInfo.biHeight; i++) {
			*(imagedata + i) = (IMAGEDATA*)malloc(sizeof(IMAGEDATA)*strInfo.biWidth);
		}
		//fseek(fpi,54,SEEK_SET);   
		
		for (i = 0; i < strInfo.biHeight; i++) {
			for (int j = 0; j < strInfo.biWidth; j++) {
				fread(*(imagedata + i) + j, sizeof(IMAGEDATA), 1, fpi);
			}
		}

		/*cout << "==================red======================" << endl;
		for (i = strInfo.biHeight - 1; i >= 0; i--) {
			for (int j = 0; j < strInfo.biWidth; j++) {
				printf("%d  ", imagedata[i][j].red);
			}
			cout << endl;
		}
		cout<<"===================green====================="<<endl;
		for(i = strInfo.biHeight - 1; i >= 0; i--) {
			for(int j = 0;j < strInfo.biWidth; j++){
				printf("%d  ", imagedata[i][j].green);
			}
			cout << endl;
		}
		cout<<"====================blue===================="<<endl;
		for(i = strInfo.biHeight - 1; i >= 0 ;i--) {
			for(int j = 0;j < strInfo.biWidth; j++){
				printf("%d  ", imagedata[i][j].blue);
			}
			cout << endl;
		} */

		int search[256][256] = { 0 };//用于操作的数组求矩形框的左上坐标和长度。
		memset(search,0,sizeof(search));
		for (i = strInfo.biHeight - 1; i >= 0; i--) {
			for (int j = 0; j < strInfo.biWidth; j++) {
				if (imagedata[i][j].red != 255) {
					search[i][j] = 1;
				}
			}
		}
		//cout << endl << "hello" << endl;

		/*for (i = strInfo.biHeight - 1; i >= 0; i--) {
			for (int j = 0; j < strInfo.biWidth; j++) {
				cout << search[i][j];
			}
			cout << endl;
		}*/
		
		/*for (i = strInfo.biHeight - 1; i >= 0; i--) {
			for (int j = 0; j < strInfo.biWidth; j++) {
				cout << search[i][j];
			}
			cout << endl;
		}*/

		Mat src = imread("E:\\wwwww.bmp");
		
		for (i = strInfo.biHeight - 1; i >= 0; i--) {
			for (int j = 0; j < strInfo.biWidth; j++) {
				if (search[i][j] == 1) {
					dfs(search, i, j);
					//cout<<endl<< minx << " " << maxy << endl;
					Rect rect(miny, strInfo.biHeight - maxx, maxy-miny, maxx-minx);//左上坐标(x,y)和矩形的长(x)宽(y)
					cv::rectangle(src, rect, Scalar(0, 0, 0), 1, LINE_8, 0);
					//cout << endl;
				}
				else {
					minx = INF;
					miny = INF;
					maxx = 0;
					maxy = 0;
				}
			}
		}
		
		imwrite("E:\\result.bmp", src);
		printf("操作后的search数组\n");
		for (i = strInfo.biHeight - 1; i >= 0; i--) {
			for (int j = 0; j < strInfo.biWidth; j++) {
				cout << search[i][j];
			}
			cout << endl;
		}

		fclose(fpi);
		cout << "成功!" << endl;
	}
	else {
		cout << "file open error!" << endl;
		return NULL;
	}
}
int main() {
	char strFile[30] = "E:\\wwwww.bmp";
	cout << strFile << endl;
	ReadFile(strFile);
	/*Mat src = imread("E:\\exp3.bmp");
	Rect rect(7, 1, 7, 5);//左上坐标(x,y)和矩形的长(x)宽(y)
	cv::rectangle(src, rect, Scalar(255, 0, 0), 1, LINE_8, 0);
	imwrite("E:\\rec.bmp", src);
	imshow("src", src);
	waitKey(20172019);*/
	system("pause");  //运行框闪退处理
	//return 0;
}

效果:

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Loganer

感谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值