C++PythonC# 三语言OpenCV从零开发(8):图像平滑处理

文章目录

  • 相关链接
  • 前言
  • 图像资源
  • 图像平滑处理
  • 图像学知识补充(重点)
    • 什么是卷积
    • 什么是图像滤波
    • 什么是方框滤波和均值滤波
  • 代码
    • Python
    • C++
    • Csharp
  • 总结

相关链接

C++&Python&Csharp in OpenCV 专栏

【2022B站最好的OpenCV课程推荐】OpenCV从入门到实战 全套课程(附带课程课件资料+课件笔记)

前言

这次来了解一下图像平滑处理。还是老套路,先写Python,再C++,再Csharp。本篇文章难的不是代码,难的是图像学的知识

图像资源

为什么Lena的那张图会成为数字图像处理的标准图?

在这里插入图片描述

图像平滑处理

图像平滑处理就是PS中常用的模糊工具,涂抹工具。算法怎么计算的可以看这个文章

数字图像处理之均值滤波

在这里插入图片描述
在这里插入图片描述

图像学知识补充(重点)

本章的难点就是图形学的知识了。这里推荐一本书【数字图像处理(中译第三版)[冈萨雷斯]】
在这里插入图片描述

目录简单展示
在这里插入图片描述

什么是卷积

卷积是一种叠加态的问题的解法。叠加态的问题有:

  • 水池有两个水龙头,一个放水一个抽水。
  • 人一天的体重变化,早餐还没彻底消化完,就吃午餐了
  • 冰箱里面的食物整体的新鲜度。不新鲜的会被拿走,新鲜的食材会被放进来
  • 湖泊的水位,下雨天水位上升,不下雨水位慢慢下降

这个就是卷积的特点:叠加状态。

那么图像的卷积是什么意思?就是考虑到每个像素对应周围像素的影响,卷积后的图像是卷积前的图像像素叠加卷积的结果。通俗点来说,就是黑色像素点周围黑一点,自己白一点。白色像素点周围白一点,自己黑一点。

就像你用墨水写字,然后用水浇上去,字就糊了。这个过程就是卷积。

如何通俗易懂地解释卷积?

瞬时行为的持续性后果,用吃冰淇淋来理解卷积

什么是图像滤波

图标滤波就是对图像的噪点进行抑制,尽量不影响图像的信息量。如果不了解这两个概念,可以近似的看成。

  • 卷积是方法论,是公式
  • 图像滤波是具体实现。

数字图像处理——图像滤波概念及方法

什么是方框滤波和均值滤波

我感觉两个差不多。

十分钟带你了解均值滤波和方框滤波

代码

Python

# %%import cv2
import matplotlib.pyplot as plt
import numpy as npimage_src = cv2.imread('d:\workSpace\OpenCV\HellOpenCV\Resources\images\lena.png')image_config = (7,7)
# 均值滤波
# 最简单的卷积操作
image_blur = cv2.blur(image_src,image_config)# 方框滤波,基本和均值一样
image_box_t = cv2.boxFilter(image_src,-1,image_config,normalize=True)
# 方框滤波,反方向
image_box_f = cv2.boxFilter(image_src,-1,image_config,normalize=False)# 高斯滤波,更重视中间值
image_gaussian = cv2.GaussianBlur(image_src,image_config,1)image_median = cv2.medianBlur(image_src,7)# 因为openCV默认BGR,Plt默认RGB,所以要转化一下
# 因为有Csharp的习惯,我习惯默认大写驼峰
def PltImshowRgb(row:int,col:int,index:int,image:np.mat,title:str):plt.subplot(row,col,index)plt.imshow(cv2.cvtColor(image,cv2.COLOR_BGR2RGB))plt.title(title)PltImshowRgb(2,3,1,image_src,'image_src')
PltImshowRgb(2,3,2,image_blur,'image_blur')
PltImshowRgb(2,3,3,image_box_t,'image_box_t')
PltImshowRgb(2,3,4,image_box_f,'image_box_f')
PltImshowRgb(2,3,5,image_gaussian,'image_gaussian')
PltImshowRgb(2,3,6,image_median,'image_median')plt.show()

在这里插入图片描述

用下来的感觉,滤波的效果确实差不多。

想详细了解其中的区别,可以看这篇文章。我就不展开说明了。

数字图像处理(11): 图像平滑 (均值滤波、中值滤波和高斯滤波)

C++

C++我自己写了一个图像合并显示的代码


#include <opencv2/opencv.hpp>  
#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc.hpp>  
#include<iostream>  
#include <vector>
using namespace std;
using namespace cv;vector<Mat> imageVector;/// <summary>
/// 将图案并排显示
/// </summary>
/// <param name="imgVector"></param>
/// <param name="dst"></param>
/// <param name="imgCols"></param>
void multipleImage(vector<Mat> imgVector, Mat& dst, int imgCols)
{const int MAX_PIXEL = 300;int imgNum = imgVector.size();//选择图片最大的一边 将最大的边按比例变为300像素Size imgOriSize = imgVector[0].size();int imgMaxPixel = max(imgOriSize.height, imgOriSize.width);//获取最大像素变为MAX_PIXEL的比例因子double prop = imgMaxPixel < MAX_PIXEL ? (double)imgMaxPixel / MAX_PIXEL : MAX_PIXEL / (double)imgMaxPixel;Size imgStdSize(imgOriSize.width * prop, imgOriSize.height * prop); //窗口显示的标准图像的SizeMat imgStd; //标准图片Point2i location(0, 0); //坐标点(从0,0开始)//构建窗口大小 通道与imageVector[0]的通道一样Mat imgWindow(imgStdSize.height * ((imgNum - 1) / imgCols + 1), imgStdSize.width * imgCols, imgVector[0].type());for (int i = 0; i < imgNum; i++){location.x = (i % imgCols) * imgStdSize.width;location.y = (i / imgCols) * imgStdSize.height;resize(imgVector[i], imgStd, imgStdSize, prop, prop, INTER_LINEAR); //设置为标准大小//imgWindow()imgStd.copyTo(imgWindow(Rect(location, imgStdSize)));}dst = imgWindow;
}int main()
{auto image = imread("D:/workSpace/OpenCV/HellOpenCV/Resources/images/lena.png");Mat showImage;Mat image_blur;Mat image_box_t;Mat image_box_f;Mat image_gaussian;Mat image_median;Size image_config = Size(7, 7);blur(image, image_blur, image_config);boxFilter(image, image_box_t, -1, image_config,Point(-1,-1),true);boxFilter(image, image_box_f,-1, image_config, Point(-1, -1), false);GaussianBlur(image, image_gaussian, image_config, 1);medianBlur(image, image_median, 7);vector<Mat> images{image,image_blur,image_box_t,image_box_f,image_gaussian,image_median};multipleImage(images, showImage, 3);imshow("C++", showImage);waitKey(0);destroyAllWindows();return 0;
}

在这里插入图片描述

Csharp

还是那句话。C++写好了,Csharp也能写。

internal class Program
{static void Main(string[] args){Mat image = Cv2.ImRead("D:/workSpace/OpenCV/HellOpenCV/Resources/images/lena.png");Mat image_blur = new Mat();Mat image_box_t = new Mat();Mat image_box_f = new Mat();Mat image_gaussian = new Mat();Mat image_median = new Mat();Size image_config = new Size(7,7);Cv2.Blur(image, image_blur, image_config);Cv2.BoxFilter(image, image_box_t, -1, image_config, new Point(-1, -1), true);Cv2.BoxFilter(image, image_box_f, -1, image_config, new Point(-1, -1), false);Cv2.GaussianBlur(image, image_gaussian, image_config, 1);Cv2.MedianBlur(image, image_median, 3);var res = MyOpenCV_Extensions.MultipleImage(new List<Mat>() { image,image_blur,image_box_t,image_box_f,image_gaussian,image_median}, 3);Cv2.ImShow("Csharp", res);Cv2.WaitKey(0);Cv2.DestroyAllWindows();}}

MyOpenCV_Extensions.cs

 public static class MyOpenCV_Extensions{/// <summary>/// 3通道遍历/// </summary>/// <param name="mat"></param>/// <returns></returns>public static int[,,] MatToArray(Mat mat){var res = new int[mat.Rows, mat.Cols, mat.Channels()];for (var i = 0; i < mat.Rows; i++){for (var j = 0; j < mat.Cols; j++){var temp = mat.At<Vec3b>(i, j);res[i, j, 0] = temp[0];res[i, j, 1] = temp[1];res[i, j, 2] = temp[2];}}return res;}public static Mat MultipleImage(List<Mat> lists, int imgCols){const int MAX_PIXEL = 300;int imgNum = lists.Count;//选择图片最大的一边 将最大的边按比例变为300像素Size imgOriSize = lists[0].Size();int imgMaxPixel = Math.Max(imgOriSize.Height, imgOriSize.Width);//获取最大像素变为MAX_PIXEL的比例因子double prop = imgMaxPixel < MAX_PIXEL ? (double)imgMaxPixel / MAX_PIXEL : MAX_PIXEL / (double)imgMaxPixel;Size imgStdSize= new Size(imgOriSize.Width* prop, imgOriSize.Height* prop); //窗口显示的标准图像的SizeMat imgStd = new Mat(); //标准图片Point location = new Point(0, 0); //坐标点(从0,0开始)//构建窗口大小 通道与imageVector[0]的通道一样Mat imgWindow = new Mat(imgStdSize.Height* ((imgNum -1) / imgCols + 1), imgStdSize.Width* imgCols, lists[0].Type());for (int i = 0; i < imgNum; i++){location.X = (i % imgCols) * imgStdSize.Width;location.Y = (i / imgCols) * imgStdSize.Height;Cv2.Resize(lists[i], imgStd, imgStdSize, prop, prop, InterpolationFlags.Linear); //设置为标准大小imgStd.CopyTo(new Mat(imgWindow, new Rect(location, imgStdSize)) ); }return imgWindow;}}

在这里插入图片描述

总结

学这个还是挺无聊的,因为刚开始就是学一些算子的使用。而且用于OpenCV没有Halcon那种进一步的封装,所以代码写起来还是挺痛苦的。最近的学习速度也有点慢下来了。最近在尽力坚持学习。

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

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

相关文章

奇安信网神 SecGate3600-authManageSet.cgi登录绕过漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

《Python 网络爬虫简易速速上手小册》第8章:分布式爬虫设计(2024 最新版)

文章目录 8.1 分布式爬虫的架构8.1.1 重点基础知识讲解8.1.2 重点案例&#xff1a;使用 Scrapy 和 Scrapy-Redis 构建分布式爬虫8.1.3 拓展案例 1&#xff1a;使用 Kafka 作为消息队列8.1.4 拓展案例 2&#xff1a;利用 Docker 容器化工作节点 8.2 分布式任务管理8.2.1 重点基础…

硬件工程师成长之路(0)----认识元件

系列文章目录 1.元件基础 2.电路设计 3.PCB设计 4.元件焊接 5.板子调试 6.程序设计 7.算法学习 8.编写exe 9.检测标准 10.项目举例 11.职业规划 文章目录 前言1、电阻①、贴片电阻②、金属膜电阻③、水泥电阻④、制动电阻⑤、电位器⑥、压敏电阻⑦、热敏电阻⑧、光敏电阻⑨…

路径索引详解

contents 一、前言二、/三、../四、./五、补充 一、前言 无论是在 Windows OS 还是在 Linux OS&#xff0c;在进行文件路径索引时&#xff0c;总能看到 / or ../ or ./ 的身影&#xff0c;下面分别解释各自的意义 二、/ / 表示从根目录开始索引 在类 Unix 操作系统中&#…

Python远程控制工具的使用

本节我们对所编写的远程控制工具的功能进行测试。首先开启主控端程序&#xff0c; 如下所示&#xff1a; 接下来打开被控端程序。当被控端打开时&#xff0c;主控端会收到被控端的连接请 求。 开启被控端程序&#xff1a; 主控端接收到连接请求并显示被控端主机的信息&#xff…

Java集合框架(包装类、泛型)

前言&#xff1a; 本篇文章我们来讲解Java中的集合框架&#xff0c;就相当于车轮子。Java是面向对象的语言&#xff0c;所以相对于C语言有自身优势&#xff0c;就比如现成的数据结构&#xff08;比如栈&#xff0c;队列&#xff0c;堆等&#xff09;。Java的集合框架大家也不用…

13 年后,我如何用 Go 编写 HTTP 服务(译)

原文&#xff1a;Mat Ryer - 2024.02.09 大约六年前&#xff0c;我写了一篇博客文章&#xff0c;概述了我是如何用 Go 编写 HTTP 服务的&#xff0c;现在我再次告诉你&#xff0c;我是如何写 HTTP 服务的。 那篇原始的文章引发了一些热烈的讨论&#xff0c;这些讨论影响了我今…

2019 年全国职业院校技能大赛高职组 “信息安全管理与评估”赛项任务书(笔记详解)

1. 网络拓扑图 2. IP 地址规划表 3. 设备初始化信息 阶段一 任务 1:网络平台搭建 1、根据网络拓扑图所示,按照 IP 地址参数表,对 DCFW 的名称、各接口IP 地址进行配置。 2、根据网络拓扑图所示,按照 IP 地址参数表,对 DCRS 的名称进行配置,创建 VLAN 并将相应接口划入 …

二十、K8S-1-权限管理RBAC详解

目录 k8s RBAC 权限管理详解 一、简介 二、用户分类 1、普通用户 2、ServiceAccount 三、k8s角色&角色绑定 1、授权介绍&#xff1a; 1.1 定义角色&#xff1a; 1.2 绑定角色&#xff1a; 1.3主体&#xff08;subject&#xff09; 2、角色&#xff08;Role和Cluster…

第三百一十六回

[tod] 我们在上一章回中介绍了"如何在输入框中处理光标"相关的内容&#xff0c;本章回中将介绍如何添加输入框默认值.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 在项目中经常使用输入框获取用户输入的内容&#xff0c;有时候在输入框中反复输入相…

城市合伙人计划:资源共享、知识交流、合作创新

城市合伙人计划是一种合作伙伴关系&#xff0c;旨在通过共享资源、知识和经验&#xff0c;共同推动城市的经济发展和社会进步。这种计划通常涉及市政府、企业、社会组织和个人等多个方面&#xff0c;通过合作共同解决城市面临的问题和挑战。 城市合伙人计划的具体形式和内容可…

基于SSM的图书管理系统

点击以下链接获取源码&#xff1a; https://download.csdn.net/download/qq_64505944/88825395?spm1001.2014.3001.5503 Java项目-14 1、导入源码 不成功导入模块也可以 2、配置jdk-一般为1.8 3、修改文件中数据库连接名与密码 4、配置Maven 5、更新Maven 7、添加数据库…

【MySQL】-12 MySQL索引(上篇MySQL索引类型前置-1)

MySQL索引 索引1 索引基础2 索引与优化1 选择索引的数据类型1.1 选择标识符 2 索引入门2.1 索引的类型2.1.1 B-Tree索引2.1.2 Hash索引2.1.3 空间(R-Tree)索引2.1.4 全文(Full-text)索引 索引的优点&#xff1a;索引是最好的解决方案吗&#xff1f; 索引 索引&#xff08;在MYS…

【笔记】Harmony学习:下载安装 DevEco Studio 开发工具IDE

IDE 安装 从官网下载DevEco Studio 安装包后进行安装&#xff0c; 安装完毕后&#xff0c;本地环境可能要配置相关工具&#xff0c;可以通过下面的诊断检测一下本地环境&#xff0c;通过蓝色“Set it up now” 可以快速安装。 1. Node.js (for ohpm) 2. ohpm 下载op的包管理&a…

精灵图,字体图标,CSS3三角

精灵图 1.1为什么需要精灵图 一个网页中往往会应用很多小的背景图像作为修饰&#xff0c;当网页中的图像过多时&#xff0c;服务器就会频繁的接受和发送请求图片&#xff0c;造成服务器请求压力过大&#xff0c;这将大大降低页面的加载速度。 因此&#xff0c;为了有效地减少…

43.1k star, 免费开源的 markdown 编辑器

简介 项目名&#xff1a; MarkText-- 简单而优雅的开源 Markdown 编辑器 Github 开源地址&#xff1a; https://github.com/marktext/marktext 官网&#xff1a; https://www.marktext.cc/ 支持平台&#xff1a; Linux, macOS 以及 Windows。 操作界面&#xff1a; 在操作界…

一场由对生成型人工智能的普遍不满引发的全面攻击正在展开

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【Linux】学习-动静态库

动静态库 头文件与库的区别 头文件一般而言&#xff0c;是声明和宏定义。头文件是在预处理阶段使用的 库文件是已经编译好的二进制代码。是一种目标文件&#xff0c;库文件是在链接阶段使用的 对于头文件和库我们可以这样理解&#xff0c;就是头文件提供的是一个函数的声明&…

使用Flash download tool进行ESP32固件烧录

背景 为方便分发固件&#xff0c;可在任意电脑上安装烧录软件&#xff0c;直接将固件烧录进 烧录内容 查看vscode上platformio的烧录过程 Writing at 0x00000000... (100 %) Wrote 15104 bytes (10401 compressed) at 0x00000000 in 0.4 seconds (effective 281.3 kbit/s).…

Pandas常用操作记录(更新中)

1.读取文件 import pandas as pd df pd.read_csv(路径) #pd.read_文件格式(路径) 2.读取某列某行&#xff0c;并使用map替换 2.1 直接读取某列数据 在获取到df对象后&#xff0c;可以使用 df.列名 来获取该列数据&#xff0c; import pandas as pd df pd.read_csv(rdat…