04. 基于MFC的数字图像处理基础框架

本文搭建一个基于MFC的图像显示平台,供同学们在学习数字图像处理的时候应用纯C++编写代码验证各类图像处理算法,以区别于其他使用高层图像处理库的平台。

博文03. 用C++类和对象封装BMP显示的相关代码介绍了如何利用MFC框架读取和显示BMP图像的问题,在此基础上,本文用一个图像取反算法来演示如何编写C++代码编写数字图像算法并立即展示效果。

首先,我们新建一个名为mfc_dsp_base的MFC单文档工程,具体方法参见之前的博文。仿照博文博文03. 用C++类和对象封装BMP显示的相关代码添加CBmp类。

接下来我们继续添加一个方便添加数字图像处理算法的类CImageProcess,系统为我们添加两个文件CImageProcess.hCImageProcess.cpp

修改文件CImageProcess.h的内容

修改文件CImageProcess.h的内容如下,除了构造函数和析构函数,添加了彩色图像变换为灰度图像的函数Color2Gray和图像取反的函数imgNegative作为示例。

#pragma once
class CImageProcess
{
public:
	CImageProcess();
	~CImageProcess();

public:
	int Color2Gray(unsigned char* R, unsigned char* G, unsigned char* B,
		int bmpWidth, int bmpHeight, unsigned char* gray_img);


	int imgNegative(unsigned char* gray_img,
		int bmpWidth, int bmpHeight);
};

修改文件CImageProcess.cpp的内容

修改文件CImageProcess.cpp的内容如下,具体实现函数Color2GrayimgNegative

#include "pch.h"
#include "CImageProcess.h"

CImageProcess::CImageProcess(){}

CImageProcess::~CImageProcess(){}

//colorful image
//加权平均法
//	I(x, y) = 0.3 * I_R(x, y) + 0.59 * I_G(x, y) + 0.11 * I_B(x, y)
int CImageProcess::Color2Gray(unsigned char* R, unsigned char* G, unsigned char* B, int bmpWidth, int bmpHeight, unsigned char* gray_img)
{
	double r,g,b;
	double gray;
	for (int i = bmpHeight - 1; i >= 0; i--)
		for (int k = 0; k < bmpWidth; k++) {
			r = (double)R[i * bmpWidth + k];
			g = (double)G[i * bmpWidth + k];
			b = (double)B[i * bmpWidth + k];

			gray = 0.3 * r + 0.59 * g + 0.11 * b;

			gray_img[i * bmpWidth + k] = (unsigned char)gray;
		}

	return 0;
}

int CImageProcess::imgNegative(unsigned char* gray_img, int bmpWidth, int bmpHeight)
{
	for (int i = bmpHeight - 1; i >= 0; i--)
		for (int k = 0; k < bmpWidth; k++) {

			gray_img[i * bmpWidth + k] = 255-gray_img[i * bmpWidth + k];
		}

	return 0;
}

有了这个基础类,我们就可以方便的在CView等界面代码中添加图像处理的代码。我们添加鼠标左键点击和右键点击两个Windows消息到工程中,在鼠标右键点击消息中添加显示原图的功能,在鼠标左键点击消息对原图取反再显示。

鼠标左键点击消息函数

#include "Bmp.h"
#include "CImageProcess.h"

CImageProcess imgProcess;
CBmp bmp;

void CmfcdspbaseView::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	//要绘制的图像文件名
	char bmpName[] = "3.bmp";
	unsigned char* red_channel = new unsigned char[1920 * 1080];
	unsigned char* green_channel = new unsigned char[1920 * 1080];
	unsigned char* blue_channel = new unsigned char[1920 * 1080];
	unsigned char* gray = new unsigned char[1920 * 1080];

	int bmpWidth = 0;
	int bmpHeight = 0;
	int biBitCount = 0;
	int lineByte = 0;

	//read bmp image
	bmp.readBmp(bmpName, red_channel, green_channel, blue_channel,&bmpWidth, &bmpHeight);

	imgProcess.Color2Gray(red_channel, green_channel, blue_channel, bmpWidth, bmpHeight, gray);
	imgProcess.imgNegative(gray, bmpWidth, bmpHeight);


	//合并绘制三个通道的图像
	CClientDC dc(this);
	CDC* pDC = &dc;

	int offset_left = point.x;
	int offset_top = point.y;

	bmp.print_matrix(pDC,
		gray,
		bmpWidth, bmpHeight,
		offset_left, offset_top);

	//important to clear the memory used
	delete[] red_channel;
	delete[] green_channel;
	delete[] blue_channel;
	delete[] gray;

	CView::OnLButtonDown(nFlags, point);
}

鼠标右键点击消息函数

void CmfcdspbaseView::OnRButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	//要绘制的图像文件名
	char bmpName[] = "3.bmp";
	unsigned char* red_channel = new unsigned char[1920 * 1080];
	unsigned char* green_channel = new unsigned char[1920 * 1080];
	unsigned char* blue_channel = new unsigned char[1920 * 1080];
	unsigned char* gray = new unsigned char[1920 * 1080];

	int bmpWidth = 0;
	int bmpHeight = 0;
	int biBitCount = 0;
	int lineByte = 0;

	//read bmp image
	bmp.readBmp(bmpName, red_channel, green_channel, blue_channel, &bmpWidth, &bmpHeight);

	imgProcess.Color2Gray(red_channel, green_channel, blue_channel, bmpWidth, bmpHeight, gray);
	//imgProcess.imgNegative(gray, bmpWidth, bmpHeight);
 
	//合并绘制三个通道的图像
	CClientDC dc(this);
	CDC* pDC = &dc;

	int offset_left = point.x;
	int offset_top = point.y;

	bmp.print_matrix(pDC,
		gray,
		bmpWidth, bmpHeight,
		offset_left, offset_top);

	//important to clear the memory used
	delete[] red_channel;
	delete[] green_channel;
	delete[] blue_channel;
	delete[] gray;

	CView::OnRButtonDown(nFlags, point);
}

这样就实现了一个简单的基于MFC的数字图像处理算法验证平台,以后可以添加新的算法到CImageProcess里面,方法仿照imgNegative即可。

扩展练习

  1. 基于C++实现直方图均衡化,并显示原图和均衡化图像。

你可能感兴趣的:(MFC数字图像处理,mfc,c++)