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

相关文章

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

Oracle的to_date()函数详解

《Oracle的to_date()函数详解》Oracle的to_date()函数用于日期格式转换,需要注意Oracle中不区分大小写的MM和mm格式代码,应使用mi代替分钟,此外,Oracle还支持毫... 目录oracle的to_date()函数一.在使用Oracle的to_date函数来做日期转换二.日

opencv实现像素统计的示例代码

《opencv实现像素统计的示例代码》本文介绍了OpenCV中统计图像像素信息的常用方法和函数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 统计像素值的基本信息2. 统计像素值的直方图3. 统计像素值的总和4. 统计非零像素的数量

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function

使用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)