图像处理算法研究的程序框架

news2025/4/19 0:09:46

目录

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/C++来开发的;使用C#来做上层调用与界面设计,是因为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值等功能。

5.3 下载地址

        开发环境:

  • Windows 10 pro x64

  • Visual Studio 2015

        下载地址: 图像处理算法研究的程序框架

参考

        图像视频滤镜与人像美颜美妆算法详解. 胡耀武、谭娟、李云夕. 电子工业出版社、2020-07

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2283636.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机工程:解锁未来科技之门!

计算机工程与应用是一个充满无限可能性的领域。随着科技的迅猛发展&#xff0c;计算机技术已经深深渗透到我们生活的方方面面&#xff0c;从医疗、金融到教育&#xff0c;无一不在彰显着计算机工程的巨大魅力和潜力。 在医疗行业&#xff0c;计算机技术的应用尤为突出。比如&a…

Linux初识——基本指令(2)

本文将继续从上篇末尾讲起&#xff0c;讲解我们剩下的基本指令 一、剩余的基本指令 1、mv mv指令是move&#xff08;移动&#xff09;的缩写&#xff0c;其功能为&#xff1a;1.剪切文件、目录。2.重命名 先演示下重命名&#xff0c;假设我想把当前目录下的di34改成dir5 那…

单片机-STM32 WIFI模块--ESP8266 (十二)

1.WIFI模块--ESP8266 名字由来&#xff1a; Wi-Fi这个术语被人们普遍误以为是指无线保真&#xff08;Wireless Fidelity&#xff09;&#xff0c;并且即便是Wi-Fi联盟本身也经常在新闻稿和文件中使用“Wireless Fidelity”这个词&#xff0c;Wi-Fi还出现在ITAA的一个论文中。…

80,【4】BUUCTF WEB [SUCTF 2018]MultiSQL

53&#xff0c;【3】BUUCTF WEB october 2019 Twice SQLinjection-CSDN博客 上面这个链接是我第一次接触二次注入 这道题也涉及了 对二次注入不熟悉的可以看看 BUUCTF出了点问题&#xff0c;打不开&#xff0c;以下面这两篇wp作为学习对象 [SUCTF 2018]MultiSQL-CSDN博客 …

Prometheus部署及linux、mysql、monog、redis、RocketMQ、java_jvm监控配置

Prometheus部署及linux、mysql、monog、redis、RocketMQ、java_jvm监控配置 1.Prometheus部署1.2.Prometheus修改默认端口 2.grafana可视化页面部署3.alertmanager部署4.监控配置4.1.主机监控node-exporter4.2.监控mysql数据库mysqld_exporter4.3.监控mongod数据库mongodb_expo…

问题排查 - TC397 CORE2 50MS/100MS任务不运行

1、问题描述 CORE2 的任务运行次数的计数值OsTask_100ms_Core2 - task_cnt[12]、OsTask_50ms_Core2 - task_cnt[16]不在累加&#xff0c;但是其他任务OsAlarm_1ms_Core2、OsAlarm_5ms_Core2、OsAlarm_10ms_Core2、OsAlarm_20ms_Core2 任务计数值累加正常。 如果是任务栈溢出&a…

Spring FatJar写文件到RCE分析

背景 现在生产环境部署 spring boot 项目一般都是将其打包成一个 FatJar&#xff0c;即把所有依赖的第三方 jar 也打包进自身的 app.jar 中&#xff0c;最后以 java -jar app.jar 形式来运行整个项目。 运行时项目的 classpath 包括 app.jar 中的 BOOT-INF/classes 目录和 BO…

百度APP iOS端磁盘优化实践(上)

01 概览 在APP的开发中&#xff0c;磁盘管理已成为不可忽视的部分。随着功能的复杂化和数据量的快速增长&#xff0c;如何高效管理磁盘空间直接关系到用户体验和APP性能。本文将结合磁盘管理的实践经验&#xff0c;详细介绍iOS沙盒环境下的文件存储规范&#xff0c;探讨业务缓…

蓝桥杯之c++入门(一)【第一个c++程序】

目录 前言一、第⼀个C程序1.1 基础程序1.2 main函数1.3 字符串1.4 头文件1.5 cin 和 cout 初识1.6 名字空间1.7 注释 二、四道简单习题&#xff08;点击跳转链接&#xff09;练习1&#xff1a;Hello,World!练习2&#xff1a;打印飞机练习3&#xff1a;第⼆个整数练习4&#xff…

14-6-1C++STL的list

(一&#xff09;list容器的基本概念 list容器简介&#xff1a; 1.list是一个双向链表容器&#xff0c;可高效地进行插入删除元素 2.list不可以随机存取元素&#xff0c;所以不支持at.(pos)函数与[ ]操作符 &#xff08;二&#xff09;list容器头部和尾部的操作 list对象的默…

【AI论文】Sigma:对查询、键和值进行差分缩放,以实现高效语言模型

摘要&#xff1a;我们推出了Sigma&#xff0c;这是一个专为系统领域设计的高效大型语言模型&#xff0c;其独特之处在于采用了包括DiffQKV注意力机制在内的新型架构&#xff0c;并在我们精心收集的系统领域数据上进行了预训练。DiffQKV注意力机制通过根据查询&#xff08;Q&…

InceptionV1_V2

目录 不同大小的感受野去提取特征 经典 Inception 网络的设计思路与运行流程 背景任务&#xff1a;图像分类&#xff08;以 CIFAR-10 数据集为例&#xff09; Inception 网络的设计思路 Inception 网络的运行流程 打个比方 多个损失函数的理解 1. 为什么需要多个损失函数&#…

ORB-SLAM2源码学习:Initializer.cc⑧: Initializer::CheckRT检验三角化结果

前言 ORB-SLAM2源码学习&#xff1a;Initializer.cc⑦: Initializer::Triangulate特征点对的三角化_cv::svd::compute-CSDN博客 经过上面的三角化我们成功得到了三维点&#xff0c;但是经过三角化成功的三维点并不一定是有效的&#xff0c;需要筛选才能作为初始化地图点。 …

【ArcGIS微课1000例】0141:提取多波段影像中的单个波段

文章目录 一、波段提取函数二、加载单波段导出问题描述:如下图所示,img格式的时序NDVI数据有24个波段。现在需要提取某一个波段,该怎样操作? 一、波段提取函数 首先加载多波段数据。点击【窗口】→【影像分析】。 选择需要处理的多波段影像,点击下方的【添加函数】。 在多…

一文大白话讲清楚webpack基本使用——17——Tree Shaking

文章目录 一文大白话讲清楚webpack基本使用——17——Tree Shaking1. 建议按文章顺序从头看&#xff0c;一看到底&#xff0c;豁然开朗2. 啥叫Tree Shaking3. 什么是死代码&#xff0c;怎么来的3. Tree Shaking的流程3.1 标记3.2 利用Terser摇起来 4. 具体使用方式4.1 适用前提…

PyCharm配置Python环境

1、打开PyCharm项目 可以从File-->Open-->选择你的项目路径-->OK&#xff0c;或者直接点击Open&#xff0c;找到项目路径-->OK&#xff0c;如图所示(点击Ok后可能有下面的弹窗&#xff0c;选择“Trust Project”即可&#xff0c;然后选择“New Window”打开项目) …

c#配置config文件

1&#xff0c;引用命名空间 Configuration 及配置信息

RDMA 工作原理 | 支持 RDMA 的网络协议

注&#xff1a;本文为 “RDMA” 相关文章合辑。 英文引文机翻未校。 图片清晰度受引文所限。 Introduction to Remote Direct Memory Access (RDMA) Written by: Dotan Barak on March 31, 2014.on February 13, 2015. What is RDMA? 什么是 RDMA&#xff1f; Direct me…

01-硬件入门学习/嵌入式教程-CH340C使用教程

前言 CH340C广泛应用于DIY项目和嵌入式开发中&#xff0c;用于USB数据转换和串口通信。本文将详细介绍CH340C的基本功能、引脚接线及使用方法。 CH340C简介 CH340C是一款USB转TTL电平转换器&#xff0c;可以将电脑的USB数据转换成串口数据&#xff0c;方便与单片机&#xff…

STM32——LCD

一、引脚配置 查看引脚 将上述引脚都设置为GPIO_Output 二、导入驱动文件 将 LCD 驱动的 Inc 以及 Src 中的 fonts.h,lcd.h 和 lcd.c 导入到自己工程的驱动文件中。 当然&#xff0c;后面 lcd 的驱动学习可以和 IMX6U 一块学。 三、LCD函数 void LCD_Clear(u16 Color); 功能…