图像处理算法研究的程序框架
目录
1 程序框架简介
2 C#图像读取、显示、保存模块
3 C动态库图像算法模块
4 C#调用C动态库
5 演示Demo
5.1 开发环境
5.2 功能介绍
5.3 下载地址
参考
1 程序框架简介
一个图像处理算法研究的常用程序逻辑框架,如下图所示

在该框架中,将图像处理算法产品分为上层模块和底层模块两个部分。
底层模块基于C/C++实现算法API,并将其提供给上层模块进行调用;上层模块负责调用API以及相关的界面功能,并最终生成适用于不同平台的软件产品。
本文主要采用C/C++语言开发图像算法API,在安全性、运行效率以及跨平台支持方面具有显著优势;相比之下,在进行上层功能实现时选择C#作为框架语言的原因是其具备强大的面向对象编程特性,并能显著提升界面设计的便捷性;此外,在处理图像读取、存储以及显示操作方面进行了较为完善的封装工作以避免复杂的编解码过程;与MFC相比这种选择使得开发过程更加简化提升了整体效率
2 C#图像读取、显示、保存模块
代码相对简单,直接给出模块代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.IO;
namespace ImageProcessDemo
{
public partial class FormMain : Form
{
public FormMain()
{
InitializeComponent();
}
#region 变量名字
// 图像文件名称
private String curFileName = null;
// 当前图像变量
private Bitmap curBitmap = null;
// 原图
private Bitmap srcBitmap = null;
#endregion
#region 图像打开和保存模块
// 图像打开
public void OpenFile()
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "所有图像文件 | *.bmp; *.pcx; *.png; *.jpg; *.gif;" +
"*.tif; *.ico; *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf|" +
"位图( *.bmp; *.jpg; *.png;...) | *.bmp; *.pcx; *.png; *.jpg; *.gif; *.tif; *.ico|" +
"矢量图( *.wmf; *.eps; *.emf;...) | *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf";
ofd.ShowHelp = true;
ofd.Title = "打开图像文件";
if (ofd.ShowDialog() == DialogResult.OK)
{
curFileName = ofd.FileName;
try
{
curBitmap = (Bitmap)System.Drawing.Image.FromFile(curFileName);
srcBitmap = new Bitmap(curBitmap);
}
catch (Exception exp)
{ MessageBox.Show(exp.Message); }
}
}
// 图像保存
public void SaveFile()
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = @"Bitmap文件(*.bmp)|*.bmp|Jpeg文件(*.jpg)|*.jpg|PNG文件(*.png)|*.png|所有合适文件(*.bmp,*.jpg,*.png)|*.bmp;*.jpg;*.png";
sfd.FilterIndex = 3;
sfd.RestoreDirectory = true;
if (sfd.ShowDialog() == DialogResult.OK)
{
ImageFormat format = ImageFormat.Jpeg;
switch (Path.GetExtension(sfd.FileName).ToLower())
{
case ".jpg":
format = ImageFormat.Jpeg;
break;
case ".bmp":
format = ImageFormat.Bmp;
break;
case ".png":
format = ImageFormat.Png;
break;
default:
MessageBox.Show("Unsupported image format was specified!");
return;
}
pictureBox1.Image.Save(sfd.FileName, format);
}
}
// 鼠标按键按下显示原图
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (srcBitmap != null)
pictureBox1.Image = srcBitmap;
}
// 鼠标按键抬起显示效果图
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (curBitmap != null)
pictureBox1.Image = curBitmap;
}
// open按钮事件
private void btn_open_Click(object sender, EventArgs e)
{
OpenFile();
if (curBitmap != null)
{
pictureBox1.Image = (Image)curBitmap;
}
}
// save按钮事件
private void btn_save_Click(object sender, EventArgs e)
{
if (pictureBox1.Image != null)
SaveFile();
}
#endregion
}
}
3 C动态库图像算法模块
构建C实现获取像素RGB值的API代码。
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include "ImageProcessAPI.h"
int getPixel(unsigned char *srcData, int width, int height, int stride, int x, int y, int rgba[4])
{
x = x < 0 ? 0 : (x > width - 1 ? width - 1 : x);
y = y < 0 ? 0 : (y > height - 1 ? height - 1 : y);
int ret = 0;
if(srcData == NULL)
{
printf("input image is null!");
return -1;
}
// 图像处理,获取像素RGBA
int pos = x * 4 + y * stride;
rgba[0] = srcData[pos + 2];
rgba[1] = srcData[pos + 1];
rgba[2] = srcData[pos + 0];
rgba[3] = srcData[pos + 3];
return ret;
};
4 C#调用C动态库
在C#中调用C/C++动态库时必须包含 System.Runtime.InteropServices 命名空间。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace ImageProcessDemo
{
unsafe class ImageProcessBitmap
{
// 引用DLL中的方法,此处ImageProcessDll为DLL的名字
[DllImport("ImageProcessDll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.None, ExactSpelling = true)]
// 封装C中的API接口,此处应注意C#和C之间的数据类型转换问题,所有参数的数据类型必须一致
// getPixel为C中的接口名称
private static extern int getPixel(byte* srcData, int width, int height, int stride, int x, int y, int[] rgba);
// C#层接口调用
// GetImgPixel为C#中封装的接口名称,该接口调用C中的getPixel
public Bitmap GetImgPixel(Bitmap src, int x, int y, ref int[] rgba)
{
// 生成图像备份
Bitmap a = new Bitmap(src);
// 获取图像的宽度和高度
int w = a.Width;
int h = a.Height;
// 获取并锁定图像数据区域
// 依据图像格式可选择16/24/32位等格式
BitmapData srcData = a.LockBits(new Rectangle(0, 0, a.Width, a.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
// 传递给C接口
getPixel((byte*)srcData.Scan0, w, h, srcData.Stride, x, y, rgba);
// 解锁图像数据区域
a.UnlockBits(srcData);
return a;
}
}
}
通过在C#界面中添加代码来实现功能:通过右键点击图像,在界面上即可观察到对应位置像素处的RGB值数值
#region 图像处理,用鼠标单击图像,界面上就会显示对应位置像素的RGB值
// 图像处理类
ImageProcessBitmap imageProcess = new ImageProcessBitmap();
// 变量
private int[] rgba = new int[4];
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (pictureBox1.Image != null)
{
curBitmap = imageProcess.GetImgPixel(srcBitmap, e.X, e.Y, ref rgba);
label_rgba.Text = "RGBA: (" + rgba[0].ToString() + "," + rgba[1].ToString() + "," + rgba[2].ToString() + "," + rgba[3].ToString() + ")";
}
}
#endregion
5 演示Demo
5.1 开发环境
Windows 10 Pro x64
Visual Studio 2015
5.2 功能介绍
演示程序的主界面如图所示,其包含以下功能模块:支持图像读取、显示和保存操作,并且能够实时更新鼠标所在位置的RGB值信息;当鼠标拖动时可实时更新该位置的RGB值信息

5.3 下载地址
开发环境:
Windows 10 pro x64
Visual Studio 2015
下载位置:图像处理相关算法研究的程序框架
参考
图像视频特效与人像美容算法深入解析. 胡耀武、谭娟、李云夕. 电子工业出版社, 2020年7月
