C#图像处理OpenCV开发指南(CVStar,04)——图片像素访问与多种局部放大效果的实现代码

​​​​​​​

使用本文代码需要预先设置一点开发环境,请阅读另外一篇博文:

C#图像处理OpenCV开发指南(CVStar,03)——基于.NET 6的图像处理桌面程序开发实践第一步icon-default.png?t=N7T8https://blog.csdn.net/beijinghorn/article/details/134684471?spm=1001.2014.3001.5502

1 功能需求

(1)读取图片;并显示于窗口;可缩放;

(2)可访问图片指定位置像素信息;

(3)提取局部图片(ROI)

(4)有 拾取框;

(5)局部放大(连续型放大);

(6)支持 大像素 型得局部放大;

(7)支持 圆形 像素的局部放大;

2 代码分段讲解

前面一个博文中出现过的代码不再赘述。

2.1 访问图片指定位置像素信息

Vec3b cx = zmt.At<Vec3b>(y, x);

y,x 指定的位置;顺序不要搞错啦! 

返回的数据类型 Vec3b 是 byte[] 类型的;BGR顺序;cx[0] 为 Blue,cx[1] 为 Green;cx[2] 为 Red;这个与一般的图片信息 RGB 顺序不同;

2.2 提取局部图片(ROI)

Mat zmt = new Mat(src, new Rect(gx, gy, gw, gh));

gx,gy 为左上角坐标;

gw,gh 为局部图片的宽度与高度(像素)。

2.3 拾取框绘制

int gw = picResult.Width / PixelSize;
int gh = picResult.Height / PixelSize;
Bitmap bmp = new Bitmap(picSource.Width, picSource.Height);
Graphics g = Graphics.FromImage(bmp);
g.DrawImage(image: img,destRect: new Rectangle(0, 0, bmp.Width, bmp.Height),srcX: 0,srcY: 0,srcWidth: img.Width,srcHeight: img.Height,srcUnit: GraphicsUnit.Pixel);
g.DrawRectangle(new Pen(Color.Yellow), mouseAtX - gw / 2, mouseAtY - gh / 2, gw, gh);
picSource.Image = bmp;

2.4 光滑的(插值的)局部放大

图片的局部放大是取局部图片,放大显示。或者直接将图片放大显示并进行移位。

非 OpenCV 方式:

Bitmap bmp = new Bitmap(picResult.Width, picResult.Height);
Graphics g = Graphics.FromImage(bmp);
g.DrawImage(image: picSource.Image,destRect: new Rectangle(0, 0, bmp.Width, bmp.Height),srcX: gx,srcY: gy,srcWidth: gw,srcHeight: gh,srcUnit: GraphicsUnit.Pixel);
picResult.Image = bmp;

OpenCV方式

Mat zmt = new Mat(src, new Rect(gx, gy, gw, gh));
picResult.Image = CVUtility.Mat2Bitmap(zmt);
PicAutosize(picResult);

2.5 非插值的大像素型放大

非插值的大像素型放大是指将原图的每个像素放大为一个矩形(块)显示。

Mat zmt = new Mat(src, new Rect(gx, gy, gw, gh));
Bitmap bmp = new Bitmap(picResult.Width, picResult.Height);
Graphics g = Graphics.FromImage(bmp);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
for (int y = 0; y < gh; y++)
{for (int x = 0; x < gw; x++){Vec3b cx = zmt.At<Vec3b>(y, x);SolidBrush sb = new SolidBrush(Color.FromArgb(cx[2], cx[1], cx[0]));g.FillRectangle(sb, new Rectangle(x * PixelSize, y * PixelSize, PixelSize, PixelSize));}
}
picResult.Image = bmp;

2.6 圆圈型像素放大算法

圆圈型像素放大算法是指将原图的每个像素放大为一个圆圈(派)显示。

Mat zmt = new Mat(src, new Rect(gx, gy, gw, gh));
Bitmap bmp = new Bitmap(picResult.Width, picResult.Height);
Graphics g = Graphics.FromImage(bmp);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
for (int y = 0; y < gh; y++)
{for (int x = 0; x < gw; x++){Vec3b cx = zmt.At<Vec3b>(y, x);SolidBrush sb = new SolidBrush(Color.FromArgb(cx[2], cx[1], cx[0]));g.FillEllipse(sb, new Rectangle(x * PixelSize, y * PixelSize, PixelSize, PixelSize));}
}
picResult.Image = bmp;

2.7 鼠标事件与拾取框

private void PicSource_MouseMove(object? sender, MouseEventArgs? e)
{if (picSource == null) { return; }if (picSource.Image == null) { return; }mouseAtX = e.X;mouseAtY = e.Y;abLocation.Text = mouseAtX + "," + mouseAtY + " " + (int)(mouseAtX / original_scale) + "," + (int)(mouseAtY / original_scale);int gw = picResult.Width / PixelSize;int gh = picResult.Height / PixelSize;Bitmap bmp = new Bitmap(picSource.Width, picSource.Height);Graphics g = Graphics.FromImage(bmp);g.DrawImage(image: img,destRect: new Rectangle(0, 0, bmp.Width, bmp.Height),srcX: 0,srcY: 0,srcWidth: img.Width,srcHeight: img.Height,srcUnit: GraphicsUnit.Pixel);g.DrawRectangle(new Pen(Color.Yellow), mouseAtX - gw / 2, mouseAtY - gh / 2, gw, gh);picSource.Image = bmp;Zoom();
}

3 运行效果

3.1 一般的插值放大算法效果

3.2 块状大像素放大效果

3.3 圆圈像素放大效果

 

4 完整的源代码

无需做修改,界面设计,直接复制粘贴替换原来的 Form1.cs 即可。

using OpenCvSharp;#pragma warning disable CS8602namespace Legal.Truffer.CVStar
{public partial class Form1 : Form{string[] ImgExtentions = {"*.*|*.*","JPEG|*.jpg;*.jpeg","GIF|*.gif","PNG|*.png","TIF|*.tif;*.tiff","BMP|*.bmp"};private int original_width { get; set; } = 0;private int original_height { get; set; } = 0;private double original_scale { get; set; } = 0.0;private string sourceImage { get; set; } = "";private int PixelSize { get; set; } = 15;private int mouseAtX { get; set; } = 0;private int mouseAtY { get; set; } = 0;Panel? panelTop { get; set; } = null;Panel? panelBotton { get; set; } = null;PictureBox? picSource { get; set; } = null;PictureBox? picResult { get; set; } = null;Button? btnLoad { get; set; } = null;RadioButton? rbSmooth { get; set; } = null;RadioButton? rbBlock { get; set; } = null;RadioButton? rbPie { get; set; } = null;Label? abLocation { get; set; }Image? img { get; set; } = null;Mat? src { get; set; } = null;public Form1(){InitializeComponent();this.Text = "OPENCV C#编程入手教程 POWERED BY 深度混淆(CSDN.NET)";this.StartPosition = FormStartPosition.CenterScreen;GUI();this.Resize += FormResize;this.DoubleBuffered = true;}private void FormResize(object? sender, EventArgs? e){if (this.Width < 200) { this.Width = 320; return; }if (this.Height < 200) { this.Height = 320; return; }mouseAtX = 0;mouseAtY = 0;GUI();}private void GUI(){if (panelTop == null) panelTop = new Panel();panelTop.Parent = this;panelTop.Top = 5;panelTop.Left = 5;panelTop.Height = 75;panelTop.Dock = DockStyle.Top;panelTop.BorderStyle = BorderStyle.FixedSingle;panelTop.BackColor = Color.FromArgb(220, 220, 255);if (panelBotton == null) panelBotton = new Panel();panelBotton.Parent = this;panelBotton.Top = panelTop.Top + panelTop.Height + 1;panelBotton.Left = 0;panelBotton.Width = panelTop.Width;panelBotton.Height = this.Height - panelBotton.Top - 55;panelBotton.BorderStyle = BorderStyle.FixedSingle;if (picSource == null) picSource = new PictureBox();picSource.Parent = panelBotton;picSource.Left = 5;picSource.Top = 5;picSource.Width = (panelBotton.Width - 10) / 2;picSource.Height = (panelBotton.Height - 10);picSource.BorderStyle = BorderStyle.FixedSingle;picSource.MouseMove += PicSource_MouseMove;picSource.DoubleClick += Load_Image;original_width = picSource.Width;original_height = picSource.Height;if (picResult == null) picResult = new PictureBox();picResult.Parent = panelBotton;picResult.Left = picSource.Left + picSource.Width + 5;picResult.Top = picSource.Top;picResult.Width = picSource.Width - (picSource.Width % PixelSize);picResult.Height = picResult.Width;picResult.BorderStyle = BorderStyle.FixedSingle;if (btnLoad == null) btnLoad = new Button();btnLoad.Parent = panelTop;btnLoad.Left = 5;btnLoad.Top = 5;btnLoad.Width = 90;btnLoad.Height = 38;btnLoad.Cursor = Cursors.Hand;btnLoad.Text = "Load";btnLoad.BackColor = Color.FromArgb(255, 110, 0);btnLoad.Click += Load_Image;if (rbSmooth == null) rbSmooth = new RadioButton();rbSmooth.Parent = panelTop;rbSmooth.Left = btnLoad.Left + btnLoad.Width + 5;rbSmooth.Top = btnLoad.Top + 5;rbSmooth.Text = "smooth";rbSmooth.Cursor = Cursors.Hand;rbSmooth.Checked = true;if (rbBlock == null) rbBlock = new RadioButton();rbBlock.Parent = panelTop;rbBlock.Left = rbSmooth.Left + rbSmooth.Width + 5;rbBlock.Top = btnLoad.Top + 5;rbBlock.Text = "block";rbBlock.Cursor = Cursors.Hand;if (rbPie == null) rbPie = new RadioButton();rbPie.Parent = panelTop;rbPie.Left = rbBlock.Left + rbBlock.Width + 5;rbPie.Top = btnLoad.Top + 5;rbPie.Text = "pie";rbPie.Cursor = Cursors.Hand;if (abLocation == null) abLocation = new Label();abLocation.Parent = panelTop;abLocation.Left = btnLoad.Left;abLocation.Top = btnLoad.Top + btnLoad.Height + 5;abLocation.Text = mouseAtX + "," + mouseAtY;PicAutosize(picSource);Zoom();}private void Load_Image(object? sender, EventArgs? e){OpenFileDialog openFileDialog = new OpenFileDialog();openFileDialog.Filter = String.Join("|", ImgExtentions);if (openFileDialog.ShowDialog() == DialogResult.OK){sourceImage = openFileDialog.FileName;img = Image.FromFile(sourceImage);picSource.Image = img;src = Cv2.ImRead(sourceImage);PicAutosize(picSource);Zoom();}}private void PicAutosize(PictureBox pb){if (pb == null) return;if (pb.Image == null) return;Image img = pb.Image;int w = original_width;int h = w * img.Height / img.Width;if (h > original_height){h = original_height;w = h * img.Width / img.Height;}if (pb == picSource){original_scale = (double)w / (double)src.Width;}pb.SizeMode = PictureBoxSizeMode.Zoom;pb.Width = w;pb.Height = h;pb.Image = img;pb.Refresh();}private void Zoom(){if (picSource == null) return;if (picSource.Image == null) return;// ROIint gw = picResult.Width / PixelSize;int gh = picResult.Height / PixelSize;int gx = (int)(mouseAtX / original_scale) - gw / 2;if (gx < 0) gx = 0;int gy = (int)(mouseAtY / original_scale) - gh / 2;if (gy < 0) gy = 0;if (rbSmooth.Checked){
#if GRAPHICS_METHODBitmap bmp = new Bitmap(picResult.Width, picResult.Height);Graphics g = Graphics.FromImage(bmp);g.DrawImage(image: picSource.Image,destRect: new Rectangle(0, 0, bmp.Width, bmp.Height),srcX: gx,srcY: gy,srcWidth: gw,srcHeight: gh,srcUnit: GraphicsUnit.Pixel);picResult.Image = bmp;
#elseMat zmt = new Mat(src, new Rect(gx, gy, gw, gh));picResult.Image = CVUtility.Mat2Bitmap(zmt);PicAutosize(picResult);
#endif}else if (rbBlock.Checked){Mat zmt = new Mat(src, new Rect(gx, gy, gw, gh));Bitmap bmp = new Bitmap(picResult.Width, picResult.Height);Graphics g = Graphics.FromImage(bmp);g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;for (int y = 0; y < gh; y++){for (int x = 0; x < gw; x++){Vec3b cx = zmt.At<Vec3b>(y, x);SolidBrush sb = new SolidBrush(Color.FromArgb(cx[2], cx[1], cx[0]));g.FillRectangle(sb, new Rectangle(x * PixelSize, y * PixelSize, PixelSize, PixelSize));}}picResult.Image = bmp;}else if (rbPie.Checked){Mat zmt = new Mat(src, new Rect(gx, gy, gw, gh));Bitmap bmp = new Bitmap(picResult.Width, picResult.Height);Graphics g = Graphics.FromImage(bmp);g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;for (int y = 0; y < gh; y++){for (int x = 0; x < gw; x++){Vec3b cx = zmt.At<Vec3b>(y, x);SolidBrush sb = new SolidBrush(Color.FromArgb(cx[2], cx[1], cx[0]));g.FillEllipse(sb, new Rectangle(x * PixelSize, y * PixelSize, PixelSize, PixelSize));}}picResult.Image = bmp;}}private void PicSource_MouseMove(object? sender, MouseEventArgs? e){if (picSource == null) { return; }if (picSource.Image == null) { return; }mouseAtX = e.X;mouseAtY = e.Y;abLocation.Text = mouseAtX + "," + mouseAtY + " " + (int)(mouseAtX / original_scale) + "," + (int)(mouseAtY / original_scale);int gw = picResult.Width / PixelSize;int gh = picResult.Height / PixelSize;Bitmap bmp = new Bitmap(picSource.Width, picSource.Height);Graphics g = Graphics.FromImage(bmp);g.DrawImage(image: img,destRect: new Rectangle(0, 0, bmp.Width, bmp.Height),srcX: 0,srcY: 0,srcWidth: img.Width,srcHeight: img.Height,srcUnit: GraphicsUnit.Pixel);g.DrawRectangle(new Pen(Color.Yellow), mouseAtX - gw / 2, mouseAtY - gh / 2, gw, gh);picSource.Image = bmp;Zoom();}}
}

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

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

相关文章

RocketMQ-RocketMQ快速实战及集群原理

一、MQ简介 ​ MQ&#xff1a;MessageQueue&#xff0c;消息队列。是在互联网中使用非常广泛的一系列服务中间件。 这个词可以分两个部分来看&#xff0c;一是Message&#xff1a;消息。消息是在不同进程之间传递的数据。这些进程可以部署在同一台机器上&#xff0c;也可以分布…

Nashorn 简介

1. 引言 本文重点介绍 Nashorn – 从 Java 8 开始&#xff0c;JVM 的新默认 JavaScript 引擎。 许多复杂的技术已被用于使 Nashorn 的性能比其前身 Rhino 高出几个数量级&#xff0c;因此这是一个值得的改变。让我们来看看它的一些使用方式。 本文大部分内容翻译自&#xff1…

element-ui表格滚动效果,el-table滚动条样式重置

项目首页需要展示一个表格滚动区域&#xff0c;特此来记录一下 HTML <div class"table-box" mouseenter"mouseenter" mouseleave"mouseleave"><el-table :data"tableList" border height"400px" v-loading"…

华为eNSP AR2220路由器配置教程

文章目录 华为eNSP AR2220路由器配置教程基础配置系统初始化设置用户密码配置设备IP地址 接口配置LAN接口配置WAN接口配置 路由配置静态路由配置动态路由协议配置OSPF配置 安全配置防火墙配置 故障排除查看接口状态日志和诊断测试网络连通性 华为eNSP AR2220路由器配置教程 华…

web前端开发简介及门槛、学习路线

1. 什么是web&#xff1f; Web是 world wide web,万维网,广域网,互联网 Web可以理解是网站 2. 什么网站和网页&#xff1f; 网站是由多个网页和其他文件组成的 3. 什么是web的前端和后端&#xff1f; 4.网页的组成&#xff1a; html: 在网页中真实存在的,例如: 文本,输入…

图像img2img任务任务中评估指标

均方误差&#xff08;Mean Squared Error&#xff0c;MSE&#xff09;&#xff1a;计算两个图像像素之间的平均差异的平方。MSE越小&#xff0c;表示两个图像越接近。 均方根误差&#xff08;Root Mean Squared Error&#xff0c;RMSE&#xff09;&#xff1a;MSE的平方根。RM…

编程之外,生活的美好航程

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

回顾Django的第二天

1.http 1.1http请求协议与响应协议 1.1.1简介 http协议包含由浏览器发送数据到服务器需要遵循的请求协议与服务器发送数据到浏览器需要遵循的请求协议。用于HTTP协议交互的信被为HTTP报文。请求端(客户端)的HTTP报文 做请求报文,响应端(服务器端)的 做响应报文。HTTP报文本身…

使用JAVA语言写一个排队叫号的小程序

以下是一个简单的排队叫号的小程序&#xff0c;使用JAVA语言实现。 import java.util.LinkedList; import java.util.Queue; import java.util.Scanner;public class NumberingSystem {public static void main(String[] args) {Queue<String> queue new LinkedList<…

PCB布线为什么不能走直角或锐角-笔记

PCB布线为什么不能走直角或锐角-笔记 摘要一.PCB走线在直角转弯的地方&#xff0c;信号前后部分相互影响这几个理由我们来一一分析一下传输线的直角带来的寄生电容从阻抗的角度来看直角的尖角产生放电或者电磁辐射走线直角的工艺问题 摘要 有一定熟悉画过PCB板的人或者PCB教学…

Linux常用命令——mv命令

文章目录 1. 简介2. 命令格式3. 主要参数4. 常见用法及示例4.1 移动文件4.2 重命名文件4.3 交互式移动文件4.4 强制移动文件4.5 移动多个文件4.6 使用通配符移动文件 5. 注意事项6. 结论 1. 简介 mv 命令在Linux系统中用于移动文件或目录&#xff0c;同时也可以用于重命名文件…

【js】如何在不指定具体属性名,而是通过变量获取属性名,设置一个对象中多层级下的某个属性的值

为了优化这种赋值方式&#xff0c;可以考虑使用ES6的解构和展开运算符。 首先&#xff0c;我们可以使用解构运算符来提取需要赋值的变量&#xff0c;以增加代码的可读性和简洁性&#xff1a; const { ContainerKey, formId } obj; obj[ContainerKey][formId[0]][formId[1]] …

Ubuntu Server 20.04.6下Anaconda3安装Pytorch

环境 Ubuntu 20.04.6 LTS Anaconda3-2023.09-0-Linux-x86_64.sh conda 23.7.4 Pytorch 1.11.0 安装 先创建一个工作环境&#xff0c;环境名叫lia&#xff1a; conda create -n lia python3.8环境的使用方法如下&#xff1a; conda activate lia # 激活环境 conda deactiv…

【Java 基础 - 泛型机制详细解释】

Java 基础 - 泛型机制详解 为什么会引入泛型泛型的基本使用 泛型类泛型接口泛型方法泛型的上下限泛型数组深入理解泛型 如何理解Java中的泛型是伪泛型&#xff1f;泛型中类型擦除如何证明类型的擦除呢&#xff1f;如何理解类型擦除后保留的原始类型?如何理解泛型的编译期检查&…

查看Hive表信息及占用空间的方法

一、Hive下查看数据表信息的方法 方法1&#xff1a;查看表的字段信息 desc table_name; 方法2&#xff1a;查看表的字段信息及元数据存储路径 desc extended table_name; 方法3&#xff1a;查看表的字段信息及元数据存储路径 desc formatted table_name; 方法4&#xff1a;…

NetApp AFF A800:为人工智能、深度学习和大数据分析提供动力

NetApp AFF A800&#xff1a;为发挥混合云的最大优势提供动力 您对数据的掌控能力将决定您能否在数字化时代取得成功。借助作为全球速度最快的企业级 NVMe 闪存存储之一的 NetApp AFF A800&#xff0c;您可以突破性能的限制。通过行业领先的云集成&#xff0c;您可以管理从边缘…

Linux:docker的数据管理(6)

数据管理操作*方便查看容器内产生的数据 *多容器间实现数据共享 两种管理方式数据卷 数据卷容器 1.数据卷 数据卷是一个供容器使用的特殊目录&#xff0c;位于容器中&#xff0c;可将宿主机的目录挂载到数据卷上&#xff0c;对数据卷的修改操作立刻可见&#xff0c;并且更新数…

Springboot快速整合kafka

kafka的基本了解 kafka也是 目前常用的消息中间件,支持同步与异步通信,和rabbitmq一样,工作模式大概相同,并且被spingboot整合的后的都是 中间件Template的实列化客户端类 ,消费者监听注解为KafkaListener,和RabbitListener和很相似,这些消息中间件使用过后,发现大致都是相同的…

基于AT89C51单片机的节日彩灯门设计

1&#xff0e;设计任务 本设计采用单片机为主控芯片&#xff0c;结合外围电路组成彩灯门的控制系统器&#xff0c;用来控制16个彩色的LED发光&#xff0c;实现彩色亮点的循环移动&#xff1b;通过软件编程实现各种各样的彩色亮点平面循环移动&#xff0c;该彩色控制器可以通过输…

fastapi 后端项目目录结构 mysql fastapi 数据库操作

原文&#xff1a;fastapi 后端项目目录结构 mysql fastapi 数据库操作_mob6454cc786d85的技术博客_51CTO博客 一、安装sqlalchemy、pymysql模块 pip install sqlalchemy -i https://pypi.tuna.tsinghua.edu.cn/simple pip install pymysql -i https://pypi.tuna.tsinghua.edu.…