目录
本来打算是分开推导的,但我觉得还是整个合集吧,避免有水文的嫌疑,那么因为学习的需要,会涉及到图像的滤波处理,我汇总了一些常见的滤波算法,方便日后查看。
我将以5*5的区域为例子来讲解:
此时,中心点就很容易的被确定了,将所有的数全部加起来后,求取平均值取代中心点的中间值,但是图像的边界并不存在5*5的区域,那么只需要提取在图像内的周围点的像素平均值。
附带草稿图:

均值滤波本身会存在缺陷,即他不能很好的保护好图像的细节,在图像去噪的同时也破坏了图像的细节部分,从而使图像变得模糊,尤其是在处理椒盐滤波的时候。
其与中值滤波相似,同样是选定固定的大小核,选取其中所有像素值的中位数作为滤波结果,类似的就是在比赛当中,去掉最高分和最低分,其余分数求取平均值,这个就叫做中位值平均滤波法,但这种方法就效率而言有点慢了。
附带草稿图:

使用一个模板,常常称为卷积或掩膜,来扫描图像中的每一个像素,用模板确定的领域内的像素的加权平均值去替代模板中心像素点的值。
附带草稿:

在高斯滤波当中,核的宽度和高度可以不相同,但都要是奇数。
同一尺寸的卷积核都可以有多种不同的形式,比如在下面的图中5*5:

同一尺寸的卷积核可以有不同的权重比,在实际的计算当中,卷积核是归一化处理的,这种处理方式可以参考上面的3*3的卷积核(都是小数的),但有的资料当中并没有进行归一化,这时就可能是如我上图当中举出来的5*5,7*7的卷积核,这样的卷积核是为了说明问题用的,实际在用的时候还是需要进行归一化,准确来说,没有经过归一化的卷积核得到的结果往往是错误的。
双边滤波是一种不同于以往的平滑滤波,是一种常用于像素边缘保持的空间非线性滤波方法,主要利用了领域内像素点的空间邻近度和像素值相似度来构建高斯权重滤波器。
附带草稿图:

图2:

引导滤波为何凯明等人于2010年提出,它本质上具有O(N)复杂度,相当于双边滤波有更好的边缘保持特性,且不会出现梯度反转的现象,在不同引导图像的引导下,可广泛应用于降噪、去雾、高动态范围压缩等。在其定义当中,用到了局部线性模型,该模型认为,某函数上一点与其邻近部分的点成线性关系,一个复杂的函数就可以用很多局部的线性函数来表示,当需要求该函数上某一点的值时,只需计算所有包含该点的线性函数的值并作平均即可。
以下皆为对此的翻译以及个人解释:
GuidedFilter.dvi (kaiminghe.com)
http://kaiminghe.com/publications/eccv10guidedfilter.pdf对于一个输入图像p,通过引导图像I,经过滤波后得到输出图像q,其中p和I都是算法的输入。引导滤波定义了如下所示的一个线性滤波过程,对于i位置的像素点,得到的滤波输出是一个加权平均值:

其中i和j分别表示像素的下标。Wij是只和引导图像I相关的滤波核。该滤波器相对于p是线性的,双边滤波核Wbf由下式给出:

其中x是像素坐标,Ki是规格化参数,以确保Wij的和为1,参数σs和σr调整空间相似性和范围(强度/颜色)相似性。联合双边滤波器退化当I和p相同时,初始双边滤波器。
现在我们定义导向滤波器及其内核。被引导者的关键假设滤波器是制导I和滤波器输出q之间的局部线性模型。我们假设q是以像素k为中心的窗口ωk中I的线性变换:

I
其中(ak,bk)是假定在ωk中为常数的一些线性系数。我们使用半径为r的方形窗口。这种局部线性模型确保q有一条边除非我有优势,因为∇q=a∇I、 该模型已被证明在图像消光、图像超分辨率和烟雾消除。为了确定线性系数,我们寻求上面式子的一个最小化的解q和滤波器输入p之间的差值。具体来说,我们将窗口中的以下成本函数:

这里是一个正则化参数,用于防止ak过大。上面的解可以通过线性回归得出:

这里,μ(k)和σ(k)**2是I在ωk中的平均值和方差,|ω|是ωk中的像素数,¯pk是ωk中p的平均值。通过此修改∇q不再是的缩放∇一、 因为线性系数(¯ai,¯bi)在空间上变化。但由于(¯ai,¯bi)是平均滤波器的输出,它们的梯度应该比强边附近的I小得多。在这种情况下,我们仍然可以∇q≈ a¯∇I、 这意味着I中的突然强度变化大部分可以在q中保持。
核重量可以明确表示为:

进一步的计算表明和的Wij(I)=1。不需要额外努力以规范化权重。
对于该算法,当I = p I=pI=p时,即输入图像和引导图像是同一副图像时,该算法即成为一个边缘保持滤波器。同时,方程的解也可作如下表示:


本文只以手写的中值滤波来实现,其他的方法滤波器大家可以自己去尝试以下:
import numpy as np
import cv2
def medianBlur(image, ksize=2):
rows, cols = image.shape[:2]
half = ksize // 2
start = half
end = rows-half-1
dst = np.zeros((rows, cols), dtype=np.uint8)
for y in range(start, end):
for x in range(start, end):
a = []
for i in range(y - half, y + half + 1):
for j in range(x - half, x + half + 1):
a.append(image[i][j])
# 取中间值
a = np.sort(a, axis=None)
if len(a) % 2 == 1:
medValue = a[len(a) // 2]
else:
medValue = int((a[len(a) // 2] + a[len(a) // 2 + 1]) / 2)
dst[y][x] = medValue
return dst
image = cv2.imread('Images/saltlena.png')
med = medianBlur(image)
# cv2.imwrite('Images/results/Med_image.png', med) #写入
cv2.imshow('image',image)
cv2.imshow('Med_image',med)
cv2.waitKey(0)
cv2.destroyAllWindows()
中值滤波效果展示:

import cv2
import numpy as np
def stackImages(scale,imgArray):
rows = len(imgArray)
cols = len(imgArray[0])
rowsAvailable = isinstance(imgArray[0], list)
width = imgArray[0][0].shape[1]
height = imgArray[0][0].shape[0]
if rowsAvailable:
for x in range ( 0, rows):
for y in range(0, cols):
if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
else:
imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
imageBlank = np.zeros((height, width, 3), np.uint8)
hor = [imageBlank]*rows
hor_con = [imageBlank]*rows
for x in range(0, rows):
hor[x] = np.hstack(imgArray[x])
ver = np.vstack(hor)
else:
for x in range(0, rows):
if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
else:
imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
hor= np.hstack(imgArray)
ver = hor
return ver
path = 'Images/Colnoiselena.jpg'
img=cv2.imread(path)
imgGray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
imgAverage=cv2.blur(img,(3,3)) #尝试改变核的大小
imgMedianBlur=cv2.medianBlur(img,3) #可以修改核的大小
imgGaussianBlur=cv2.GaussianBlur(imgGray,(7,7),1.8)
imgBilater=cv2.bilateralFilter(img,9,75,75)
imgStack = stackImages(0.6,([img,imgGray,imgAverage],[imgMedianBlur,imgGaussianBlur,imgBilater]))
cv2.imshow("imges",imgStack)
cv2.waitKey(0)
效果图:
在我运行引导滤波的函数时出现了找不到模块的问题:
AttributeError: 'cv2.ximgproc.GuidedFilter' object has no attribute 'shape'
可能是版本号的问题,有的函数可能申请了专利,由于我之前装opencv的时候很麻烦,所以这里我找了别的大佬的代码,大家可以看看。
import cv2 as cv
from matplotlib import pyplot as plt
import numpy as np
R = 16 # 滤波半径
r = 2 * R + 1
s = 1 # 快速引导滤波(如果大于0)
def read(path):
"""读入图片"""
src = cv.imread(path)
return src
def To_HSV(image):
"""转化为HSV空间"""
dst = cv.cvtColor(image, cv.COLOR_BGR2HSV) # opencv是BGR模式
H, S, V = cv.split(dst)
cv.imshow('V', V)
return H, S, V
def To_BGR(H, S, V):
dst = cv.merge([H, S, V])
dst = cv.cvtColor(dst, cv.COLOR_HSV2BGR)
cv.imshow('dst', dst)
return dst
def LSE(V):
V_down = cv.resize(V, (V.shape[1] // s, V.shape[0] // s))
V_32 = V_down.astype(np.float32)
V_2 = np.square(V_32)
dst1 = cv.boxFilter(V_2, ddepth=-1, ksize=(r, r), normalize=True,
borderType=cv.BORDER_DEFAULT) # 盒式滤波(True为归一化均值滤波),效率高之关键,类似积分图
# print(dst1)
u_k = cv.boxFilter(V_32, ddepth=-1, ksize=(r, r), normalize=True,
borderType=cv.BORDER_DEFAULT) # 默认为cv.BORDER_REFLECT101,镜像
u_k_2 = np.square(u_k)
sigma_k = dst1 - u_k_2 # D(X)= E(X2)- E(X)2
print('最大方差为:', np.max(sigma_k)) # kesi的取值应与此同量级,以使方差发挥自适应调节作用(ak公式)
kesi = 10000 # 重要参数(太小则全部保留梯度信息,没有任何平滑(ak==1);太大则等价于均值滤波了)
a_k = (dst1 - u_k * u_k) / (sigma_k + kesi)
b_k = u_k - a_k * u_k
# print(a_k)
return a_k, b_k, V_down
def light(a_k, b_k, V_down, V):
a = cv.boxFilter(a_k, ddepth=-1, ksize=(r, r), normalize=True)
b = cv.boxFilter(b_k, ddepth=-1, ksize=(r, r), normalize=True)
I_down = a * V_down + b
# cv.imshow('I_down',I_down)
I = cv.resize(I_down, (V.shape[1], V.shape[0]))
I = np.where(I > 255, 255, I) # 可用clip函数
I = np.where(I < 0, 0, I)
I_ = I.astype(np.uint8)
cv.imshow('I', I_)
return I
if __name__ == '__main__':
path = 'Images/Colnoiselena.jpg' # 修改为自己路径
src = read(path)
cv.imshow('src', src)
H, S, V = To_HSV(src)
ak, bk, V_down = LSE(V)
I = light(ak, bk, V_down, V)
cv.waitKey(0)
cv.destroyAllWindows()

均值滤波:卷积核越大,图片的失真越明显,图片会更模糊,如果设置核的大小为(1,1),则结果是原始图像。
中值滤波:随着核的增大,图片会更加模糊,核必须是大于1的奇数,如3,5,7等,在这cv2.medianBlur(src,ksize)当中,填写核时填写一个数字,如3,5,7,在这里我们要对比均值滤波的用法。它对于椒盐噪声的图片效果最好。
高斯滤波:随着核的大小逐渐变大,会让图像更加模糊,核的大小(N,N)必须是大于1的奇数,如3,5,7等,sigma表示的是X方向方差。我们常常在边缘检测中用到它。
双边滤波:具有平滑但保持边缘的特性,而且双边滤波常常用在人像美化上,其他的比如上面的几个都会将图片变模糊。
引导滤波:相对于双边滤波最大的优点是在于算法的复杂度与窗口的大小无关,对于处理较为大型的图片时,在效率上有明显的提升,同时引导滤波可以很好的克服双边滤波当中的梯度翻转的现象,它的线性的计数量,可以显著的提高处理的效率。
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司
首先回顾一下拉格朗日定理的内容:函数f(x)是在闭区间[a,b]上连续、开区间(a,b)上可导的函数,那么至少存在一个,使得:通过这个表达式我们可以知道,f(x)是函数的主体,a和b可以看作是主体函数f(x)中所取的两个值。那么可以有, 也就意味着我们可以用来替换 这种替换可以用在求某些多项式差的极限中。方法: 外层函数f(x)是一致的,并且h(x)和g(x)是等价无穷小。此时,利用拉格朗日定理,将原式替换为 ,再进行求解,往往会省去复合函数求极限的很多麻烦。使用要注意:1.要先找到主体函数f(x),即外层函数必须相同。2.f(x)找到后,复合部分是等价无穷小。3.要满足作差的形式。如果是加
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
我正在尝试使用Ruby2.0.0和Rails4.0.0提供的API从imgur中提取图像。我已尝试按照Ruby2.0.0文档中列出的各种方式构建http请求,但均无济于事。代码如下:require'net/http'require'net/https'defimgurheaders={"Authorization"=>"Client-ID"+my_client_id}path="/3/gallery/image/#{img_id}.json"uri=URI("https://api.imgur.com"+path)request,data=Net::HTTP::Get.new(path
2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p
有这样的事吗?我想在Ruby程序中使用它。 最佳答案 试试这个http://csl.sublevel3.org/jp2a/此外,Imagemagick可能还有一些东西 关于ruby-是否有将图像文件转换为ASCII艺术的命令行程序或库?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6510445/
我正在使用Dragonfly在Rails3.1应用程序上处理图像。我正在努力通过url将图像分配给模型。我有一个很好的表格:{:multipart=>true}do|f|%>RemovePicture?Dragonfly的文档指出:Dragonfly提供了一个直接从url分配的访问器:@album.cover_image_url='http://some.url/file.jpg'但是当我在控制台中尝试时:=>#ruby-1.9.2-p290>picture.image_url="http://i.imgur.com/QQiMz.jpg"=>"http://i.imgur.com/QQ
我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby-vips的github页面上的链接,我们将不胜感激!如果有ruby-
我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d