主页 > 电脑硬件  > 

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

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

​​​​​​​

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

C#图像处理OpenCV开发指南(CVStar,03)——基于.NET 6的图像处理桌面程序开发实践第一步 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 CS8602 namespace 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; // ROI int 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_METHOD 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; #else Mat 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(); } } }

标签:

C#图像处理OpenCV开发指南(CVStar,04)——图片像素访问与多种局部放大效果的实现代码由讯客互联电脑硬件栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“C#图像处理OpenCV开发指南(CVStar,04)——图片像素访问与多种局部放大效果的实现代码