当前位置: 首页 > article >正文

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

2023-12-04 应网友叮嘱,发表完整的工程代码:

Visual Studio 2022 完整工程(全)icon-default.png?t=N7T8https://download.csdn.net/download/beijinghorn/88597423

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();
        }
    }
}


http://www.kler.cn/a/157355.html

相关文章:

  • WPF Binding 绑定
  • 模仿elementui的Table,实现思路
  • leetcode之hot100---240搜索二维矩阵II(C++)
  • 【Qt】显示类控件:QLabel、QLCDNumber、QProgressBar、QCalendarWidget
  • 如何实现单例模式?
  • 探索 CI/CD 工具的力量
  • TensorRT-LLM保姆级教程(一)-快速入门
  • 价差后的几种方向,澳福如何操作才能盈利
  • web自动化 -- pyppeteer
  • 计算机网络(二)| 物理层上 | 数据通信基础知识 调制 频率范围 信噪比
  • 数据结构与算法(四)分治算法(Java)
  • Python 3 读写 json 文件
  • 小程序长按识别二维码
  • UE中C++创建对象方法不完全汇总
  • gitlab高级功能之CI/CD组件 - 实践(二)
  • Android Framework 电池提醒相关Dialog熄屏消失的问题
  • Redis实战篇笔记(最终篇)
  • Java核心知识点整理大全18-笔记
  • 简单的界面与数据分离的架构
  • TensorRT-LLM保姆级教程(二)-离线环境搭建、模型量化及推理
  • 十二月四日多继承
  • 2024 年甘肃省职业院校技能大赛中职组 电子与信息类“网络安全”赛项竞赛样题-C
  • 竞赛选题YOLOv7 目标检测网络解读
  • CSS实现瀑布流
  • MyBatis 设计模式解析
  • KaiwuDB 多模数据库-时序性能优化