opencv函数GaussianBlur,pyrDown,pyrUp深究

2023-10-21 21:38

本文主要是介绍opencv函数GaussianBlur,pyrDown,pyrUp深究,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

通常在使用GaussianBlur,pyrDown,pyrUp的时候都不会深究的内部实现,最近想自己实现一下,看看会遇到哪些问题,然后将结果和opencv的函数运行结果进行对比。
C++: void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT )

从GaussianBlur的参数可以看出,有sigmaX 和sigmaY, 二维高斯核使用的是分别在X和Y方向进行一维高斯核卷积来模拟二维高斯核的效果。

对于边界问题,BORDER_DEFAULT 是指:pixel[-1]使用pixel[1]的像素值来代替,pixel[-2] = pixel[2],pixel[width] = pixel[width - 2],依此类推(如果pixel[0],pixel[width -1]为边界的话) 。

	for (int row = 0 ;row <src.rows ;row++)//x orientation{for (int col = 0 ; col <src.cols; col++){float sumRed = 0,sumGreen = 0,sumBlue = 0;for (int subcol = -win_size;subcol<=win_size;subcol++){int srccol = col+subcol;if (srccol<0){srccol *= -1;}if (srccol>=src.cols){srccol = src.cols*2 - srccol - 2;}sumRed += kernel[subcol+win_size]*src.at<Vec3b>(row,srccol)[2];sumGreen += kernel[subcol+win_size]*src.at<Vec3b>(row,srccol)[1];sumBlue += kernel[subcol+win_size]*src.at<Vec3b>(row,srccol)[0];}temp.at<Vec3b>(row,col)[2] = sumRed;temp.at<Vec3b>(row,col)[1] = sumGreen;temp.at<Vec3b>(row,col)[0] = sumBlue;}}for (int row = 0 ;row <src.rows ;row++)//y orientation{for (int col = 0 ; col <src.cols; col++){float sumRed = 0,sumGreen = 0,sumBlue = 0;for (int subrow = -win_size;subrow<=win_size;subrow++){int srcrow = row+subrow;if (srcrow<0){srcrow *= -1;}if (srcrow>=src.rows){srcrow = src.rows*2 - srcrow - 2;;}sumRed += kernel[subrow+win_size]*temp.at<Vec3b>(srcrow,col)[2];sumGreen += kernel[subrow+win_size]*temp.at<Vec3b>(srcrow,col)[1];sumBlue += kernel[subrow+win_size]*temp.at<Vec3b>(srcrow,col)[0];}result.at<Vec3b>(row,col)[2] = sumRed;result.at<Vec3b>(row,col)[1] = sumGreen;result.at<Vec3b>(row,col)[0] = sumBlue;}}

C++: void pyrDown(InputArray src, OutputArray dst, const Size& dstsize=Size())

pyrDown 是降采样,分两步进行。

第一步:对src图像进行模糊,使用的模糊核不是高斯核,而是这样一个核函数


第二步:模糊之后的图像去除所有偶数行和偶数列。
void GassianPyramid::downSampleFunc(Mat src, Mat& result)
{int width = src.cols;int height = src.rows;int ow = width/2;  int oh = height/2;  result.create(Size(ow,oh),src.type());float tempArr[5][5]={1,4,6,4,1,4,16,24,16,4,6,24,36,24,6,4,16,24,16,4,1,4,6,4,1};for (int i = 0;i<5;i++){for (int j = 0; j<5; j++){tempArr[i][j] /=256;}}Mat temp;temp.create(Size(src.cols,src.rows),src.type());for (int row = 0 ;row <src.rows ;row++){for (int col = 0 ; col <src.cols; col++){float sumRed = 0,sumGreen = 0,sumBlue = 0;for (int subrow = -win_size;subrow<=win_size;subrow++){int srcrow = row+subrow;if (srcrow<0){srcrow *= -1;}if (srcrow>=src.rows){srcrow = (src.rows - 1) - (srcrow - (src.rows-1));}for (int subcol = -win_size;subcol<=win_size;subcol++){int srccol = col+subcol;if (srccol<0){srccol *= -1;}if (srccol>=src.cols){srccol = (src.cols - 1) - (srccol - (src.cols-1));}sumRed += tempArr[subrow+win_size][subcol+win_size]*src.at<Vec3b>(srcrow,srccol)[2];sumGreen += tempArr[subrow+win_size][subcol+win_size]*src.at<Vec3b>(srcrow,srccol)[1];sumBlue += tempArr[subrow+win_size][subcol+win_size]*src.at<Vec3b>(srcrow,srccol)[0];}}temp.at<Vec3b>(row,col)[2] = sumRed;temp.at<Vec3b>(row,col)[1] = sumGreen;temp.at<Vec3b>(row,col)[0] = sumBlue;}}int inRow=0, inCol = 0;  		for(int row=0; row<oh; row++) {  for(int col=0; col<ow; col++) {  inRow = 2* row;  inCol = 2* col;  if(inRow >= height) {  inRow = height;  }  if(inCol >= width) {  inCol = width;  }  result.at<Vec3b>(row,col)[2]= temp.at<Vec3b>(inRow,inCol)[2];result.at<Vec3b>(row,col)[1]= temp.at<Vec3b>(inRow,inCol)[1];result.at<Vec3b>(row,col)[0]= temp.at<Vec3b>(inRow,inCol)[0];}  }
}

C++: void pyrUp(InputArray src, OutputArray dst, const Size& dstsize=Size())
pyrUp是上采样,也是分两步进行。第一步:将图像在每个方向扩大为原来的两倍,新增的行和列以0填充。

 第二步:将 
上面降采样的高斯核*4和放大后的图像进行卷积。 
void GassianPyramid::expendSampleFunc(Mat src, Mat& result)
{int width = src.cols;int height = src.rows;int ow = 2*width;  int oh =2*height; Mat temp;temp.create(Size(ow,oh),src.type());result.create(Size(ow,oh),src.type());for(int row=0; row<oh; row++) {  for(int col=0; col<ow; col++) {  int inRow = row/2;  int inCol = col/2;if(row - inRow*2 > 0 || col - inCol*2 > 0) {  temp.at<Vec3b>(row,col)[2] = 0;temp.at<Vec3b>(row,col)[1] = 0;temp.at<Vec3b>(row,col)[0] = 0;continue;} temp.at<Vec3b>(row,col)[2] = src.at<Vec3b>(inRow,inCol)[2];temp.at<Vec3b>(row,col)[1] = src.at<Vec3b>(inRow,inCol)[1];temp.at<Vec3b>(row,col)[0] = src.at<Vec3b>(inRow,inCol)[0];}  }  float tempArr[5][5]={1,4,6,4,1,4,16,24,16,4,6,24,36,24,6,4,16,24,16,4,1,4,6,4,1};for (int i = 0;i<5;i++){for (int j = 0; j<5; j++){tempArr[i][j] /=64;}}for (int row = 0 ;row <temp.rows ;row++){for (int col = 0 ; col <temp.cols; col++){float sumRed = 0,sumGreen = 0,sumBlue = 0;for (int subrow = -win_size;subrow<=win_size;subrow++){int srcrow = row+subrow;if (srcrow<0){srcrow *= -1;}if (srcrow>=temp.rows){srcrow = (temp.rows - 1) - (srcrow - (temp.rows-1));}for (int subcol = -win_size;subcol<=win_size;subcol++){int srccol = col+subcol;if (srccol<0){srccol *= -1;}if (srccol>=temp.cols){srccol = (temp.cols - 1) - (srccol - (temp.cols-1));}sumRed += tempArr[subrow+win_size][subcol+win_size]*temp.at<Vec3b>(srcrow,srccol)[2];sumGreen += tempArr[subrow+win_size][subcol+win_size]*temp.at<Vec3b>(srcrow,srccol)[1];sumBlue += tempArr[subrow+win_size][subcol+win_size]*temp.at<Vec3b>(srcrow,srccol)[0];}}result.at<Vec3b>(row,col)[2] = sumRed;result.at<Vec3b>(row,col)[1] = sumGreen;result.at<Vec3b>(row,col)[0] = sumBlue;}}
}


结果发现,和opencv自带的函数运行结果相同,证明结果正确。







这篇关于opencv函数GaussianBlur,pyrDown,pyrUp深究的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/257124

相关文章

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

opencv 滚动条

参数介绍:createTrackbar( trackbarname , "hello" , &alpha_slider ,alpha_max ,  on_trackbar )  ;在标签中显示的文字(提示滑动条的用途) TrackbarName创建的滑动条要放置窗体的名字 “hello”滑动条的取值范围从 0 到 alpha_max (最小值只能为 zero).滑动后的值存放在

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

C++操作符重载实例(独立函数)

C++操作符重载实例,我们把坐标值CVector的加法进行重载,计算c3=c1+c2时,也就是计算x3=x1+x2,y3=y1+y2,今天我们以独立函数的方式重载操作符+(加号),以下是C++代码: c1802.cpp源代码: D:\YcjWork\CppTour>vim c1802.cpp #include <iostream>using namespace std;/*** 以独立函数

函数式编程思想

我们经常会用到各种各样的编程思想,例如面向过程、面向对象。不过笔者在该博客简单介绍一下函数式编程思想. 如果对函数式编程思想进行概括,就是f(x) = na(x) , y=uf(x)…至于其他的编程思想,可能是y=a(x)+b(x)+c(x)…,也有可能是y=f(x)=f(x)/a + f(x)/b+f(x)/c… 面向过程的指令式编程 面向过程,简单理解就是y=a(x)+b(x)+c(x)

利用matlab bar函数绘制较为复杂的柱状图,并在图中进行适当标注

示例代码和结果如下:小疑问:如何自动选择合适的坐标位置对柱状图的数值大小进行标注?😂 clear; close all;x = 1:3;aa=[28.6321521955954 26.2453660695847 21.69102348512086.93747104431360 6.25442246899816 3.342835958564245.51365061796319 4.87

OpenCV结构分析与形状描述符(11)椭圆拟合函数fitEllipse()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C++11 算法描述 围绕一组2D点拟合一个椭圆。 该函数计算出一个椭圆,该椭圆在最小二乘意义上最好地拟合一组2D点。它返回一个内切椭圆的旋转矩形。使用了由[90]描述的第一个算法。开发者应该注意,由于数据点靠近包含的 Mat 元素的边界,返回的椭圆/旋转矩形数据

Unity3D 运动之Move函数和translate

CharacterController.Move 移动 function Move (motion : Vector3) : CollisionFlags Description描述 A more complex move function taking absolute movement deltas. 一个更加复杂的运动函数,每次都绝对运动。 Attempts to

树莓派5_opencv笔记27:Opencv录制视频(无声音)

今日继续学习树莓派5 8G:(Raspberry Pi,简称RPi或RasPi)  本人所用树莓派5 装载的系统与版本如下:  版本可用命令 (lsb_release -a) 查询: Opencv 与 python 版本如下: 今天就水一篇文章,用树莓派摄像头,Opencv录制一段视频保存在指定目录... 文章提供测试代码讲解,整体代码贴出、测试效果图 目录 阶段一:录制一段