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.hqwc.cn/news/235506.html

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

相关文章

CMake 教程:常用命令及其使用方法

CMake是一个跨平台、开源的构建工具&#xff0c;它可以自动生成Makefile或者Visual Studio等IDE的工程文件。它能够帮助开发者更方便地管理项目的构建过程&#xff0c;提高项目构建的效率。在本文中&#xff0c;我们将介绍CMake常用的命令以及对应的用法 add_executable add_e…

sql注入基础篇

sql注入基础 漏洞原理 对用户输入的数据没有做参数校验&#xff0c;sql语句没有做安全处理&#xff0c;导致用户可以通过参数控制sql语句从而查询一些敏感数据&#xff0c;甚至控制对方主机 漏洞利用 前置知识 ​ 1、首先不同的数据库&#xff0c;漏洞注入的方式也不同&#x…

Unity 一些常用注解

在Unity中有一些比较常用的注解&#xff1a; 1、[SerializeField]&#xff1a;将私有字段或属性显示在 Unity 编辑器中&#xff0c;使其可以在 Inspector 窗口中进行编辑。 2、[Range(min, max)]&#xff1a;限制数值字段或属性的范围&#xff0c;在 Inspector 窗口中以滑动条…

Selenium定位元素的方法css和xpath的区别!

selenium是一种自动化测试工具&#xff0c;它可以通过不同的定位方式来识别网页上的元素&#xff0c;如id、name、class、tag、link text、partial link text、css和xpath。 css和xpath是两种常用的定位方式&#xff0c;它们都可以通过元素的属性或者层级关系来定位元素&#…

【CAN通信】CanIf模块详细介绍

目录 1.内容简介 2.CanIf详细设计 2.1 CanIf功能简介 2.2 一些关键概念 2.3依赖的上下层模块 2.4 功能详细设计 2.4.1 Hardware object handles 2.4.2 Static L-PDUs 2.4.3 Dynamic L-PDUs 2.4.4 Dynamic Transmit L-PDUs 2.4.5 Dynamic receive L-PDUs 2.4.6Physi…

第16关 革新云计算:如何利用弹性容器与托管K8S实现极速服务POD扩缩容

------> 课程视频同步分享在今日头条和B站 天下武功&#xff0c;唯快不破&#xff01; 大家好&#xff0c;我是博哥爱运维。这节课给大家讲下云平台的弹性容器实例怎么结合其托管K8S&#xff0c;使用混合服务架构&#xff0c;带来极致扩缩容快感。 下面是全球主流云平台弹…

Hiera实战:使用Hiera实现图像分类任务(一)

文章目录 摘要安装包安装timm 数据增强Cutout和MixupEMA项目结构计算mean和std生成数据集 摘要 现代层次视觉变换器在追求监督分类表现时增加了几个特定于视觉的组件。 这些组件虽然带来了有效的准确性和吸引人的FLOP计数&#xff0c;但增加的复杂性实际上使这些变换器比普通V…

MySQL表的查询、更新、删除

查询 全列查询 指定列查询 查询字段并添加自定义表达式 自定义表达式重命名 查询指定列并去重 select distinct 列名 from 表名 where条件 查询列数据为null的 null与 (空串)是不同的&#xff01; 附&#xff1a;一般null不参与查询。 查询列数据不为null的 查询某列数据指定…

时序预测 | Python实现GA-TCN-LSTM遗传算法-时间卷积神经网络-长短期记忆网络时间序列预测

时序预测 | Python实现GA-TCN-LSTM遗传算法-时间卷积神经网络-长短期记忆网络时间序列预测 目录 时序预测 | Python实现GA-TCN-LSTM遗传算法-时间卷积神经网络-长短期记忆网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 使用先进的机器学习技术和优化算法…

【C++】了解模板

这里是目录 前言函数模板函数模板的实例化类模板 前言 如果我们要交换两个数字&#xff0c;那么我们就需要写一个Swap函数来进行交换&#xff0c;那如果我们要交换char类型的数据呢&#xff1f;那又要写一份Swap的函数重载&#xff0c;参数的两个类型是char&#xff0c;那我们…

免费WordPress站群插件-批量管理站群的免费软件

WordPress站群插件&#xff1a;让文章管理如丝般顺滑 在众多网站建设工具中&#xff0c;WordPress一直以其简便易用、丰富的插件生态而备受青睐。对于站群管理者而言&#xff0c;如何高效地更新、发布和推送文章是一项不可忽视的任务。本文将专注分享一款WordPress站群插件&am…

Vue语音播报,不用安装任何包和插件,直接调用。

Vue语音播报功能可以通过使用浏览器提供的Web Speech API来实现。这个API允许你的应用程序通过浏览器朗读文本&#xff0c;不用安装任何包和插件&#xff0c;直接调用。以下是一个简单的介绍&#xff0c;演示如何在Vue中使用语音提示功能&#xff1a; 一、JS版本 <template…