首页 > 其他分享 >OpenCV4.9处理平滑图像

OpenCV4.9处理平滑图像

时间:2024-04-07 17:02:08浏览次数:13  
标签:src return OpenCV4.9 int 平滑 display DELAY 图像 dst

返回:OpenCV系列文章目录(持续更新中......)

上一篇:使用OpenCV4.9的随机生成器和文本

下一篇:OpenCV系列文章目录(持续更新中......)

目标

在本教程中,您将学习如何使用 OpenCV 函数将不同的线性滤波器应用于平滑图像,例如:

  • blur()
  • GaussianBlur()
  • medianBlur()
  • bilateralFilter()

相关理论

注意

下面的解释属于 Richard Szeliski 的《计算机视觉:算法和应用》一书和 LearningOpenCV

  • 平滑,也称为模糊,是一种简单且常用的图像处理操作。
  • 平滑的原因有很多。在本教程中,我们将重点介绍平滑处理以减少噪声(其他用途将在以下教程中看到)。
  • 它有助于将滤镜可视化为在图像上滑动的系数窗口。

  • 过滤器有很多种,这里我们提一下最常用的:

归一化盒过滤器

  • 这个过滤器是最简单的!每个输出像素都是其内核邻居的平均(所有像素的权重相等)
  • 内核如下:

高斯滤波器

  • 可能是最有用的过滤器(虽然不是最快的)。高斯滤波是通过用高斯核对输入数组中的每个点进行卷积,然后将它们相加以生成输出数组来完成的。
  • 为了让图片更清晰,还记得一维高斯核的样子吗?

假设图像是 1D 的,您可以注意到位于中间的像素将具有最大的权重。其相邻像素的权重随着它们与中心像素之间的空间距离的增加而减小。

注意

请记住,二维高斯可以表示为:

中值滤波器

中值滤波器贯穿信号的每个元素(在本例中为图像),并将每个像素替换为其相邻像素的中位数(位于评估像素周围的方形邻域中)。

双边过滤器

  • 到目前为止,我们已经解释了一些过滤器,其主要目标是平滑输入图像。然而,有时滤波器不仅可以溶解噪声,还可以消除边缘。为了避免这种情况(至少在一定程度上),我们可以使用双边过滤器。
  • 与高斯滤波器类似,双边滤波器也会考虑相邻像素,并为每个像素分配权重。这些权重有两个组成部分,第一个分量与高斯滤波器使用的权重相同。第二个组件考虑了相邻像素和评估像素之间的强度差异。
  • 有关更详细的说明,您可以查看此链接

代码:

  • 这个程序是做什么的?
    • 加载图像
    • 应用 4 种不同类型的滤镜(在理论中解释)并按顺序显示滤波后的图像
  • 可下载代码: 点击这里
  • 代码一览:

C++: 

 
#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
 
using namespace std;
using namespace cv;
 
int DELAY_CAPTION = 1500;
int DELAY_BLUR = 100;
int MAX_KERNEL_LENGTH = 31;
 
Mat src; Mat dst;
char window_name[] = "Smoothing Demo";
 
int display_caption( const char* caption );
int display_dst( int delay );
 
 
int main( int argc, char ** argv )
{
 namedWindow( window_name, WINDOW_AUTOSIZE );
 
 const char* filename = argc >=2 ? argv[1] : "lena.jpg";
 
 src = imread( samples::findFile( filename ), IMREAD_COLOR );
 if (src.empty())
 {
 printf(" Error opening image\n");
 printf(" Usage:\n %s [image_name-- default lena.jpg] \n", argv[0]);
 return EXIT_FAILURE;
 }
 
 if( display_caption( "Original Image" ) != 0 )
 {
 return 0;
 }
 
 dst = src.clone();
 if( display_dst( DELAY_CAPTION ) != 0 )
 {
 return 0;
 }
 
 if( display_caption( "Homogeneous Blur" ) != 0 )
 {
 return 0;
 }
 
 for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
 {
 blur( src, dst, Size( i, i ), Point(-1,-1) );
 if( display_dst( DELAY_BLUR ) != 0 )
 {
 return 0;
 }
 }
 
 if( display_caption( "Gaussian Blur" ) != 0 )
 {
 return 0;
 }
 
 for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
 {
 GaussianBlur( src, dst, Size( i, i ), 0, 0 );
 if( display_dst( DELAY_BLUR ) != 0 )
 {
 return 0;
 }
 }
 
 if( display_caption( "Median Blur" ) != 0 )
 {
 return 0;
 }
 
 for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
 {
 medianBlur ( src, dst, i );
 if( display_dst( DELAY_BLUR ) != 0 )
 {
 return 0;
 }
 }
 
 if( display_caption( "Bilateral Blur" ) != 0 )
 {
 return 0;
 }
 
 for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
 {
 bilateralFilter ( src, dst, i, i*2, i/2 );
 if( display_dst( DELAY_BLUR ) != 0 )
 {
 return 0;
 }
 }
 
 display_caption( "Done!" );
 
 return 0;
}
 
int display_caption( const char* caption )
{
 dst = Mat::zeros( src.size(), src.type() );
 putText( dst, caption,
 Point( src.cols/4, src.rows/2),
 FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) );
 
 return display_dst(DELAY_CAPTION);
}
 
int display_dst( int delay )
{
 imshow( window_name, dst );
 int c = waitKey ( delay );
 if( c >= 0 ) { return -1; }
 return 0;
}

Java:

import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
 
class SmoothingRun {
 
 int DELAY_CAPTION = 1500;
 int DELAY_BLUR = 100;
 int MAX_KERNEL_LENGTH = 31;
 
 Mat src = new Mat(), dst = new Mat();
 String windowName = "Filter Demo 1";
 
 public void run(String[] args) {
 
 String filename = ((args.length > 0) ? args[0] : "../data/lena.jpg");
 
 src = Imgcodecs.imread(filename, Imgcodecs.IMREAD_COLOR);
 if( src.empty() ) {
 System.out.println("Error opening image");
 System.out.println("Usage: ./Smoothing [image_name -- default ../data/lena.jpg] \n");
 System.exit(-1);
 }
 
 if( displayCaption( "Original Image" ) != 0 ) { System.exit(0); }
 
 dst = src.clone();
 if( displayDst( DELAY_CAPTION ) != 0 ) { System.exit(0); }
 
 if( displayCaption( "Homogeneous Blur" ) != 0 ) { System.exit(0); }
 
 for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2) {
 Imgproc.blur(src, dst, new Size(i, i), new Point(-1, -1));
 displayDst(DELAY_BLUR);
 }
 
 if( displayCaption( "Gaussian Blur" ) != 0 ) { System.exit(0); }
 
 for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2) {
 Imgproc.GaussianBlur(src, dst, new Size(i, i), 0, 0);
 displayDst(DELAY_BLUR);
 }
 
 if( displayCaption( "Median Blur" ) != 0 ) { System.exit(0); }
 
 for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2) {
 Imgproc.medianBlur(src, dst, i);
 displayDst(DELAY_BLUR);
 }
 
 if( displayCaption( "Bilateral Blur" ) != 0 ) { System.exit(0); }
 
 for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2) {
 Imgproc.bilateralFilter(src, dst, i, i * 2, i / 2);
 displayDst(DELAY_BLUR);
 }
 
 displayCaption( "Done!" );
 
 System.exit(0);
 }
 
 int displayCaption(String caption) {
 dst = Mat.zeros(src.size(), src.type());
 Imgproc.putText(dst, caption,
 new Point(src.cols() / 4, src.rows() / 2),
 Imgproc.FONT_HERSHEY_COMPLEX, 1, new Scalar(255, 255, 255));
 
 return displayDst(DELAY_CAPTION);
 }
 
 int displayDst(int delay) {
 HighGui.imshow( windowName, dst );
 int c = HighGui.waitKey( delay );
 if (c >= 0) { return -1; }
 return 0;
 }
}
 
public class Smoothing {
 public static void main(String[] args) {
 // Load the native library.
 System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
 new SmoothingRun().run(args);
 }
}

Python:

 

import sys
import cv2 as cv
import numpy as np
 
# Global Variables
 
DELAY_CAPTION = 1500
DELAY_BLUR = 100
MAX_KERNEL_LENGTH = 31
 
src = None
dst = None
window_name = 'Smoothing Demo' 
 
def main(argv):
 cv.namedWindow(window_name, cv.WINDOW_AUTOSIZE)
 
 # Load the source image
 imageName = argv[0] if len(argv) > 0 else 'lena.jpg'
 
 global src
 src = cv.imread(cv.samples.findFile(imageName))
 if src is None:
 print ('Error opening image')
 print ('Usage: smoothing.py [image_name -- default ../data/lena.jpg] \n')
 return -1
 
 if display_caption('Original Image') != 0:
 return 0
 
 global dst
 dst = np.copy(src)
 if display_dst(DELAY_CAPTION) != 0:
 return 0
 
 # Applying Homogeneous blur
 if display_caption('Homogeneous Blur') != 0:
 return 0 
 
 for i in range(1, MAX_KERNEL_LENGTH, 2):
 dst = cv.blur(src, (i, i))
 if display_dst(DELAY_BLUR) != 0:
 return 0 
 
 # Applying Gaussian blur
 if display_caption('Gaussian Blur') != 0:
 return 0 
 
 for i in range(1, MAX_KERNEL_LENGTH, 2):
 dst = cv.GaussianBlur(src, (i, i), 0)
 if display_dst(DELAY_BLUR) != 0:
 return 0 
 
 # Applying Median blur
 if display_caption('Median Blur') != 0:
 return 0 
 
 for i in range(1, MAX_KERNEL_LENGTH, 2):
 dst = cv.medianBlur(src, i)
 if display_dst(DELAY_BLUR) != 0:
 return 0 
 
 # Applying Bilateral Filter
 if display_caption('Bilateral Blur') != 0:
 return 0 
 
 for i in range(1, MAX_KERNEL_LENGTH, 2):
 dst = cv.bilateralFilter(src, i, i * 2, i / 2)
 if display_dst(DELAY_BLUR) != 0:
 return 0 
 
 # Done
 display_caption('Done!')
 
 return 0 
 
def display_caption(caption):
 global dst
 dst = np.zeros(src.shape, src.dtype)
 rows, cols, _ch = src.shape
 cv.putText(dst, caption,
 (int(cols / 4), int(rows / 2)),
 cv.FONT_HERSHEY_COMPLEX, 1, (255, 255, 255))
 
 return display_dst(DELAY_CAPTION) 
 
def display_dst(delay):
 cv.imshow(window_name, dst)
 c = cv.waitKey(delay)
 if c >= 0 : return -1
 return 0 
 
if __name__ == "__main__":
 main(sys.argv[1:])

解释

让我们检查一下仅涉及平滑过程的 OpenCV 函数,因为其余的现在已经知道了。

归一化块滤波器:

  • OpenCV 提供了函数 blur() 来使用此过滤器执行平滑处理。我们指定 4 个参数(更多详细信息,请查看参考):
    • src:源图片
    • dst:目标图像
    • Size( w, h ):定义要使用的内核的大小(宽度 w 像素和高度 h 像素)
    • Point(-1, -1):指示锚点(评估的像素)相对于邻域的位置。如果存在负值,则将内核的中心视为锚点。
    • C++:
 for i in range(1, MAX_KERNEL_LENGTH, 2):
 dst = cv.blur(src, (i, i))
 if display_dst(DELAY_BLUR) != 0:
 return 0

 Java:

 for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2) {
 Imgproc.blur(src, dst, new Size(i, i), new Point(-1, -1));
 displayDst(DELAY_BLUR);
 }

Python: 

 for i in range(1, MAX_KERNEL_LENGTH, 2):
 dst = cv.blur(src, (i, i))
 if display_dst(DELAY_BLUR) != 0:
 return 0

Gaussian Filter:

  • 它由函数 GaussianBlur() 执行: 这里我们使用 4 个参数(更多细节,请查看 OpenCV 参考):

C++:

 for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
 {
 GaussianBlur( src, dst, Size( i, i ), 0, 0 );
 if( display_dst( DELAY_BLUR ) != 0 )
 {
 return 0;
 }
 }

Java:

 for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2) {
 Imgproc.blur(src, dst, new Size(i, i), new Point(-1, -1));
 displayDst(DELAY_BLUR);
 }

python:

 for i in range(1, MAX_KERNEL_LENGTH, 2):
 dst = cv.GaussianBlur(src, (i, i), 0)
 if display_dst(DELAY_BLUR) != 0:
 return 0

中值过滤器:

  • 此过滤器由 medianBlur()函数提供: 我们使用三个参数:
    • src:源图片
    • dst:目标镜像,必须与 src 类型相同
    • i:内核的大小(只有一个,因为我们使用方形窗口)。一定是奇怪的。

C++:

 for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
 {
 medianBlur ( src, dst, i );
 if( display_dst( DELAY_BLUR ) != 0 )
 {
 return 0;
 }
 }

Java:

 for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2) {
 Imgproc.medianBlur(src, dst, i);
 displayDst(DELAY_BLUR);
 }

Python: 

 for i in range(1, MAX_KERNEL_LENGTH, 2):
 dst = cv.medianBlur(src, i)
 if display_dst(DELAY_BLUR) != 0:
 return 0

双边过滤器

  • 由 OpenCV 函数 bilateralFilter() 提供 我们使用 5 个参数:
    • src:源图片
    • dst:目标图像
    • d:每个像素邻域的直径。

C++:

 for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
 {
 bilateralFilter ( src, dst, i, i*2, i/2 );
 if( display_dst( DELAY_BLUR ) != 0 )
 {
 return 0;
 }
 }

Java:

 for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2) {
 Imgproc.bilateralFilter(src, dst, i, i * 2, i / 2);
 displayDst(DELAY_BLUR);
 }

Python:

 # Remember, bilateral is a bit slow, so as value go higher, it takes long time
 for i in range(1, MAX_KERNEL_LENGTH, 2):
 dst = cv.bilateralFilter(src, i, i * 2, i / 2)
 if display_dst(DELAY_BLUR) != 0:
 return 0

结果

  • 该代码打开一个图像(在本例中为 lena.jpg),并在解释的 4 个过滤器的影响下显示它。
  • 以下是使用 medianBlur 平滑处理的图像快照:


参考文献:

1、《Smoothing Images》--------Ana Huamán​​​​​​​

标签:src,return,OpenCV4.9,int,平滑,display,DELAY,图像,dst
From: https://blog.csdn.net/2301_78348935/article/details/137467136

相关文章

  • opencv4.9.0交叉编译教程
    opencv4.9.0交叉编译教程1.准备工作在linux系统中下载opencv源码;在linux系统中安装cmake-gui;linux系统具有嵌入式板卡对应的交叉编译工具链,且能够正常使用。2.配置opencv​​​​​​​​勾选opencl(如果你芯片支持),opengl(如果你芯片支持),openmp。​​​​使能zLI......
  • 11.java openCV4.x 入门- Imgcodecs之图像读写
    专栏简介......
  • Canon CMOS图像传感器应用和选型
    一、CCD和CMOS图像传感器常见的数字感光元件有两种:CCD(电荷耦合器件)和CMOS(互补金属氧化物半导体)。1980年代,CCD进入消费级市场,并长期占据中高端市场。CMOS图像传感器最初作为廉价、低画质的代名词,但是在2008年之后逐渐成为市场主流。如今已经广泛应用于手机、汽车、安防、医疗、......
  • 【复数值图像去噪】ADMM和超光谱宽带相位恢复中的光谱近邻算子,用于定量相位成像(Matlab
     ......
  • 图像识别与增强现实(AR)的结合
    图像识别与增强现实(AR)的结合是当今技术领域的一个热点,它通过将数字信息叠加到现实世界的视觉呈现中,为用户提供了一种全新的交互体验。这种技术融合了计算机视觉、图像处理、传感器融合、人机交互等多个技术领域的最新成果,广泛应用于娱乐、教育、医疗、零售等多个行业。增强......
  • OpenCV中表示图像的类Mat在QT里的基本使用
    在Qt中使用OpenCV的Mat类来表示和处理图像是相对简单的,因为Qt和OpenCV都是跨平台的,并且可以很好地在一起工作。以下是如何在Qt项目中使用OpenCV的Mat类的基本步骤:1.在Qt代码中包含OpenCV头文件在Qt的源代码文件中,你需要包含OpenCV的头文件以及opencv统一的命名空间来使用Mat......
  • 数字图像处理、计算机图形学相关的名词解释和解答题(二)
    声明1.本系列的主要内容主要是罗列《数字图像处理》和《计算机图形学》这两门课程中涉及到的一些名词解释和简答题。2.其中名词解释不仅仅是解释这个名词,还包括其结果、原理、类型或优缺点等方面的解释,以保证答题时字数足够。可以根据自身情况进行增添。3.适合即将期末考......
  • 两个专栏帮你搞定【图像拼接(image stitching)】
    【图像拼接论文精读】专栏:图像拼接论文精读【图像拼接源码精读】专栏:图像拼接论文源码精读前言图像拼接(imagestitching)是计算机视觉中的高级图像处理手段,是一个小众方向,研究的人很少,自然也没有人做这个领域的专栏教程。一方面,入门该邻域的难度大、门槛高,需要强大的数学、图形......
  • 将24位BMP图像转换为8位BMP图像的实现方法
    项目说明周末想起一个项目需要使用agg与8bits的BMP进行绘制,因agg不支持8bitsBMP进行绘制,故自己实现了一个基于agg+rgb88进行绘制,绘制结果转为8bits的BMP.从24位BMP图像到8位BMP图像的转换过程。转换后的图像文件将只使用256种颜色,但仍保留了原始图像的基本信息。主要原理:读......
  • DUT-图像简易灰度
    模板-V1模型功能输入视频总线输出视频总线将RGB24数据转化为灰度数据模型框图控制模型实现步骤源码编写未经仿真的原始代码`timescale1ns/1ps/**/////////////////////////////////////////////////////////////////////////////////////Company://Eng......