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

news2024/11/25 6:44:46

文章目录

  • 相关链接
  • 前言
  • 图像资源
  • 图像平滑处理
  • 图像学知识补充(重点)
    • 什么是卷积
    • 什么是图像滤波
    • 什么是方框滤波和均值滤波
  • 代码
    • 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 np

image_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); //窗口显示的标准图像的Size

	Mat 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); //窗口显示的标准图像的Size

         Mat 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.coloradmin.cn/o/1433837.html

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

相关文章

UE4运用C++和框架开发坦克大战教程笔记(十七)(第51~54集)

UE4运用C和框架开发坦克大战教程笔记&#xff08;十七&#xff09;&#xff08;第51~54集&#xff09; 51. UI 框架介绍UE4 使用 UI 所面临的问题以及解决思路关于即将编写的 UI 框架的思维导图 52. 管理类与面板类53. 预加载与直接加载54. UI 首次进入界面 51. UI 框架介绍 U…

c#string方法对比

字符串的截取匹配操作在开发中非常常见&#xff0c;比如下面这个示例&#xff1a;我要匹配查找出来字符串数组中以“abc”开头的字符串并打印&#xff0c;我下面分别用了两种方式实现&#xff0c;代码如下&#xff1a; using System; namespace ConsoleApp23{ class Progra…

【计算机网络】物理层概述|通信基础|奈氏准则|香农定理|信道复用技术

目录 一、思维导图 二、 物理层概述 1.物理层概述 2.四大特性&#xff08;巧记"械气功程") 三、通信基础 1.数据通信基础 2.趁热打铁☞习题训练 3.信号の变身&#xff1a;编码与调制 4.极限数据传输率 5.趁热打铁☞习题训练 6.信道复用技术 推荐 前些天发…

flutter开发实战-可扩展popup弹窗template模版样式

flutter开发实战-可扩展popup弹窗template模版样式 最近在看到一个flutter_beautiful_popup&#xff0c;可以美化弹窗窗口样式。该插件通过一个template模版的类BeautifulPopupTemplate作为抽象的base类。 一、基类BeautifulPopupTemplate 在BeautifulPopupTemplate中&…

前端面试题——Vue的双向绑定

前言 双向绑定机制是Vue中最重要的机制之一&#xff0c;甚至可以说是Vue框架的根基&#xff0c;它将数据与视图模板相分离&#xff0c;使得数据处理和页面渲染更为高效&#xff0c;同时它也是前端面试题中的常客&#xff0c;接下来让我们来了解什么是双向绑定以及其实现原理。…

可解释性对人工智能发展的影响

文章目录 每日一句正能量前言可解释AI已成热点可解释性人工智能的重要性可解释性人工智能的研究现状推动可解释模型构建未来展望后记 每日一句正能量 不好等待运气降临&#xff0c;就应去发奋掌握知识。 前言 随着人工智能技术的快速发展&#xff0c;越来越多的应用场景需要人…

神经网络激活函数到底是什么?

激活函数 其实不是很难啦&#xff0c;归结一下就是大概这样几个分类&#xff0c;详情请参考【神经网络】大白话直观理解&#xff01;_哔哩哔哩_bilibili神经网络就是干这个事的~ 如果队伍不长&#xff0c;一个ykxb就可以了&#xff0c;如果 如果 队伍太长 就加一个激活函数也…

HBase相关面试准备问题

为什么选择HBase 1、海量存储 Hbase适合存储PB级别的海量数据&#xff0c;在PB级别的数&#xff0c;能在几十到几百毫秒内返回数据。这与Hbase的极易扩展性息息相关。正是因为Hbase良好的扩展性&#xff0c;才为海量数据的存储提供了便利。 2、列式存储 这里的列式存储其实说的…

Verilog实现2进制码与BCD码的互相转换

1、什么是BCD码&#xff1f; BCD码是一种2进制的数字编码形式&#xff0c;用4位2进制数来表示1位10进制中的0~9这10个数。这种编码技术&#xff0c;最常用于会计系统的设计里&#xff0c;因为会计制度经常需要对很长的数字做准确的计算。相对于一般的浮点式记数法&#xff0c;…

微信小程序 --- 腾讯地图线路规划

目录 微信小程序JavaScript 简介 Hello world&#xff01; geocoder(options:Object) 微信小程序插件 简介 路线规划插件 入驻腾讯位置服务平台 申请开发者密钥&#xff08;Key&#xff09;&#xff1a;申请秘钥 Key的作用与注意事项 微信公众平台绑定插件 方式一&a…

新型IT运维管理,基础设施和数据两手都要硬

编前语&#xff1a;数据是AI的基石&#xff0c;缺数据无AI。 AI大模型时代&#xff0c;数据赋予IT人“新使命” 当下IT人在企业中扮演着运营支撑的角色。说到运维管理&#xff0c;相信每人都是一把辛酸泪&#xff0c;每天承担着繁琐、高负荷且又高风险的运维工作&#xff0c;但…

开源软件全景解析:驱动技术创新与行业革新的力量

目录 什么是开源 开源的核心 开源软件的特点 为什么程序员应该拥抱开源 1.学习机会&#xff1a; 2.社区支持&#xff1a; 3.提高职业竞争力&#xff1a; 4.加速开发过程&#xff1a; 5.贡献和回馈&#xff1a; 开源软件的影响力 开源软件多元分析&#xff1a; 开源…

机器学习中常用的性能度量—— ROC 和 AUC

什么是泛化能力&#xff1f; 通常我们用泛化能力来评判一个模型的好坏&#xff0c;通俗的说&#xff0c;泛化能力是指一个机器学期算法对新样本&#xff08;即模型没有见过的样本&#xff09;的举一反三的能力&#xff0c;也就是学以致用的能力。 举个例子&#xff0c;高三的…

为什么说TiDB在线扩容对业务几乎没有影响

作者&#xff1a; 数据源的TiDB学习之路 原文来源&#xff1a; https://tidb.net/blog/e82b2c5f 当前的数据库种类繁多&#xff0c;墨天轮当前统计的所有国产数据库已经有 290个 &#xff0c;其中属于关系型数据库的有 166个 。关系型数据库从部署架构上又可以分为集中式…

AI克隆自己的声音只需5秒,MockingBird实现AI克隆声音!

一、环境搭建 搭建Anaconda运行环境 搭建Anaconda运行环境请跳转链接查看https://blog.csdn.net/m0_50269929/article/details/136036402安装pytorch pip3 install torch torchvision torchaudio安装ffmpeg 打开官网 https://ffmpeg.org/download.html#get-packages 下载地址…

Python实现PDF到HTML的转换

PDF文件是共享和分发文档的常用选择&#xff0c;但提取和再利用PDF文件中的内容可能会非常麻烦。而利用Python将PDF文件转换为HTML是解决此问题的理想方案之一&#xff0c;这样做可以增强文档可访问性&#xff0c;使文档可搜索&#xff0c;同时增强文档在不同场景中的实用性。此…

InnoDB 锁系统(小白入门)

1995年 &#xff0c;MySQL 1.0发布&#xff0c;仅供内部使用&#xff01; 开发多用户、数据库驱动的应用时&#xff0c;最大的一个难点是&#xff1a;一方面要最大程度地利用数据库的并发访问&#xff0c;另一方面还要确保每个用户能以一致性的方式读取和修改数据。 MVCC 并发…

list基本使用

list基本使用 构造迭代器容量访问修改 list容器底层是带头双向链表结构&#xff0c;可以在常数范围内在任意位置进行输入和删除&#xff0c;但不支持任意位置的随机访问&#xff08;如不支持[ ]下标访问&#xff09;&#xff0c;下面介绍list容器的基本使用接口。 template <…

CSS-IN-JS

CSS-IN-JS 为什么会有CSS-IN-JS CSS-IN-JS是web项目中将CSS代码捆绑在JavaScript代码中的解决方案。 这种方案旨在解决CSS的局限性&#xff0c;例如缺乏动态功能&#xff0c;作用域和可移植性。 CSS-IN-JS介绍 1&#xff1a;CSS-IN-JS方案的优点&#xff1a; 让css代码拥…

探索数据可视化:Matplotlib在Python中的高效应用

探索数据可视化&#xff1a;Matplotlib在Python中的高效应用 引言Matplotlib基础安装和配置Matplotlib基础概念绘制简单图表线形图散点图柱状图 图表定制和美化修改颜色、线型和标记添加标题、图例和标签使用样式表和自定义样式 高级图表类型绘制高级图表多图布局和复杂布局交互…