使用opencv实现图像滤波

1 图像滤波介绍

滤波是信号和图像处理中的基本任务之一,其旨在有选择地提取图像的某些特征,可以用于在给定应用程序的上下文中传达重要信息,例如,去除图像中的噪声、提取所需的视觉特征、图像重采样等。

1.1 图像滤波理论

图像滤波即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作。消除图像中的噪声又叫做图像滤波或平滑,滤波的目的有两个,一是突出特征以方便处理,二是抑制噪声。

空间域滤波就是在图像平面上对像素进行操作。空间域滤波大体分为两类:平滑、锐化。

  • 平滑滤波:模糊处理,用于减小噪声,实际上是低通滤波,典型的滤波器是高斯滤波。

  • 锐化滤波:提取边缘突出边缘及细节、弥补平滑滤波造成的边缘模糊。实际上是高通滤波。

空间域处理可由下式表示:

g(x,y)=T[f(x,y)]

式中,f(x,y)是输入图像,g(x,y)是处理后的图像,T是在点(x,y)的邻域上定义的关于f的一种算子,算子可应用于单幅图像或图像集合。

1.2  频域分析

频域分析 (frequency domain analysis) :不同图像具有不同的灰度分布,可以用图像的灰度分布作为表征图像的一种方式,但同时,还存在另一种分析图像的观点。观察图像中的灰度变化,可以发现,某些图像包含强度几乎恒定的大面积区域(例如,蓝天),而某些图像上的灰度强度变化很快(例如,拥挤的街道)。因此,可以用图像中的变化频率作为表征图像的另一种方式,这种方式被称为频域,而通过观察图像的灰度分布来表征图像的方式则被称为空间域。

频域分析将图像从最低频率到最高频率分解为其频率内容,图像强度缓慢变化的区域仅包含低频,而高频是由强度的快速变化产生的。有多种用于计算图像的频率内容的变换,例如傅立叶变换或余弦变换。需要注意的是,由于图像是二维平面,因此频率由垂直频率(垂直方向的变化)和水平频率(水平方向的变化)组成。

在频域分析中,滤波器是一种放大图像某些频带同时减少其他频带的操作。因此,低通滤波器 (low-pass filters) 是消除图像高频成分的滤波器,而高通滤波器 (high-pass filters) 消除图像的低频成分。

1.3 邻域滤波算子

  • 空间滤波器由一个邻域(通常是一个较小的矩形)和对该邻域所包围图像像素执行的预定义操作组成。对预定义的点(x,y)为中心的领域内的像素进行计算。

  • 滤波产生一个新像素,用计算后的新像素值代替点(x,y)的值。

  • 循环步骤1和2,滤波器的中心遍历图像中的每个像素后,就生成了滤波后的图像。

  • 如果在图像像素上执行的是线性操作,则该滤波器称为线性空间滤波器,否则,称为非线性空间滤波器。

一般来说,使用大小为 m×n的滤波器对大小为 M×N的图像进行线性空间滤波,可由下式表示:

 2 opencv图像滤波

2.1 opencv滤波概述

滤波处理分为两大类:线性滤波和非线性滤波。OpenCV里有这些滤波的函数,使用起来非常方便。

2.1.1 线性滤波

  • 方框滤波BoxBlur:模糊图像

  • 均值滤波Blur:模糊图像

  • 高斯滤波GaussianBlur:信号的平滑处理,去除符合正太分布的噪声

平滑滤波:一般来说,图像具有局部连续的性质,即相邻的像素的值相近,而噪声使得噪点处产生像素跳跃,所以通过平滑噪点可以减少噪声,去除图像中的不相关细节。

方框滤波BoxBlur和均值滤波Blur都是对邻域内做平均值来滤波,属于平滑滤波。滤波的输出是包含在滤波器模板邻域内的像素的平均值,方框滤波做归一化之后就变为均值滤波,这两个滤波器都是低通滤波器。

高斯滤波:高斯滤波对于图像来说就是一个低通滤波,广泛用于消除高斯噪声,高速滤波就是一种加权滤波,只不过模板中的系数由高斯分布来确定的,高斯滤波器根据高斯函数的形状来选择滤波模板权值的线性平滑滤波器。高斯平滑滤波器对于抑制服从正态分布的噪声非常有效。

2.1.2 非线性滤波:

  • 中值滤波mediaBlur:去除椒盐噪声

  • 双边滤波BilateralFilter:保边去噪

中值滤波:中值滤波属于非线性滤波,其思想用滤波模板邻域内的像素的平均值来代替像素点的灰度值。中值滤波器是一种统计排序滤波器,图像上点(x,y),中值滤波以该点为中心,领域内所有像素的统计排序中值作为此点的响应,中值滤波是非线性滤波。相比与均值滤波和高斯滤波,中值滤波可以有效的降低随机噪声,直接忽略掉噪声点,把噪声引起的模糊降到最低。线性滤波器在滤波的同时会造成图像细节模糊,中值滤波可以避免这个问题,其典型的应用就是中值滤波消除斑点噪声、椒盐噪声。

双边滤波:高斯滤波属于加权平均滤波,距离中心点越近的点越有较大权重,这种方法符合图像的平滑变化的特征,但是在边缘区域,像素值出现突变,这种方法反而会滤掉边缘轮廓,损失掉有用的边缘信息。边缘保护滤波方法,双边滤波就是最常用的边缘保护滤波方法,就是为了处理这种情况而发明的。

双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。双边滤波将高斯滤波中通过各个点到中心点的空间临近度计算的各个权值进行优化,将其优化为空间临近度计算的权值和像素值相似度计算的权值的乘积,优化后的权值再与图像作卷积运算,从而达到保边去噪的效果。

2.2 opencv核心概念

  • 低通滤波:低通滤波可以去除图像的噪音或平滑图像。

  • 高通滤波:可以帮助查找图像的边缘。

  • 噪音:即对一幅图像的产生负面效果,过暗或过亮的部分,一幅图像中,低于或高于某个像素点的值,都可以认为是噪音。

  • 卷积核:即用来滤波的矩阵,卷积核一般为奇数,如3×3、5×5、7×7等;

  • 锚点:卷积核最中间的坐标点。

  • 卷积核越大,卷积的效果越好,但是计算量随之也会增大。

  • 边界扩充:当卷积核大于1,并且不进行边界扩充,输出尺寸相应缩小、当卷积核一标准方式进行边界扩充,则输出的空间尺寸与输入相等。

  • 图像卷积

3 opencv图像滤波实现

2.1 filter2D:图像卷积

函数原型:

    dst = cv2.filter2D(src, ddepth, kernel, anchor, delta, borderType)
   

    src:原图像

    ddepth:输出图像的尺寸,默认为-1

    kernel:卷积核(是一个矩阵)

    anchor:锚点,默认随卷积核变化

    delta:卷积后加一个值,默认为0

    borderType:有映射类型,加一个黑边,默认不设置

示例代码:

import cv2
import numpy as np# 一个窗口显示多张图片
def show_multi_imgs(scale, imglist, order=None, border=10, border_color=(255, 255, 0)):""":param scale: float 原图缩放的尺度:param imglist: list 待显示的图像序列:param order: list or tuple 显示顺序 行×列:param border: int 图像间隔距离:param border_color: tuple 间隔区域颜色:return: 返回拼接好的numpy数组"""if order is None:order = [1, len(imglist)]allimgs = imglist.copy()ws , hs = [], []for i, img in enumerate(allimgs):if np.ndim(img) == 2:allimgs[i] = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)allimgs[i] = cv2.resize(img, dsize=(0, 0), fx=scale, fy=scale)ws.append(allimgs[i].shape[1])hs.append(allimgs[i].shape[0])w = max(ws)h = max(hs)# 将待显示图片拼接起来sub = int(order[0] * order[1] - len(imglist))# 判断输入的显示格式与待显示图像数量的大小关系if sub > 0:for s in range(sub):allimgs.append(np.zeros_like(allimgs[0]))elif sub < 0:allimgs = allimgs[:sub]imgblank = np.zeros(((h+border) * order[0], (w+border) * order[1], 3)) + border_colorimgblank = imgblank.astype(np.uint8)for i in range(order[0]):for j in range(order[1]):imgblank[(i * h + i*border):((i + 1) * h+i*border), (j * w + j*border):((j + 1) * w + j*border), :] = allimgs[i * order[1] + j]return imgblankoriginal = cv2.imread('../data/girl03.jpeg')# 创建一个5*5的卷积核
kernel = np.ones((5, 5), np.float32) / 25
filter2d = cv2.filter2D(original, -1, kernel)img = show_multi_imgs(2, [original, filter2d], (1, 2))
cv2.namedWindow('origi&filter2D', 0)
cv2.imshow('origi&filter2D', img)
cv2.waitKey(0)

运行代码显示如下:

 经过图像处理后,看着变模糊了,图像更平滑了

2.2 低通滤波boxFilter:方盒滤波

函数原型:

dst = cv2.boxFilter(src, ddepth, ksize , anchor, normalize, borderType)

src:输入图像
ddepth:输出图像的尺寸,默认为-1
kernel:卷积核大小(x, y)
anchor:锚点,默认随卷积核变化
normalize:布尔类型默认为True;True:a为1/W*H(均值滤波),false:a=1

borderType:有映射类型,加一个黑边,默认不设置

示例代码:

import cv2
import numpy as np# 一个窗口显示多张图片
def show_multi_imgs(scale, imglist, order=None, border=10, border_color=(255, 255, 0)):""":param scale: float 原图缩放的尺度:param imglist: list 待显示的图像序列:param order: list or tuple 显示顺序 行×列:param border: int 图像间隔距离:param border_color: tuple 间隔区域颜色:return: 返回拼接好的numpy数组"""if order is None:order = [1, len(imglist)]allimgs = imglist.copy()ws , hs = [], []for i, img in enumerate(allimgs):if np.ndim(img) == 2:allimgs[i] = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)allimgs[i] = cv2.resize(img, dsize=(0, 0), fx=scale, fy=scale)ws.append(allimgs[i].shape[1])hs.append(allimgs[i].shape[0])w = max(ws)h = max(hs)# 将待显示图片拼接起来sub = int(order[0] * order[1] - len(imglist))# 判断输入的显示格式与待显示图像数量的大小关系if sub > 0:for s in range(sub):allimgs.append(np.zeros_like(allimgs[0]))elif sub < 0:allimgs = allimgs[:sub]imgblank = np.zeros(((h+border) * order[0], (w+border) * order[1], 3)) + border_colorimgblank = imgblank.astype(np.uint8)for i in range(order[0]):for j in range(order[1]):imgblank[(i * h + i*border):((i + 1) * h+i*border), (j * w + j*border):((j + 1) * w + j*border), :] = allimgs[i * order[1] + j]return imgblankimg = cv2.imread('../data/girl03.jpeg')# 方盒滤波(当为True时)变成均值滤波,当为False时,就只加和不变化,超过255的结果设置为255
img2 = cv2.boxFilter(img, -1, (5, 5), normalize=True)
img3 = cv2.boxFilter(img, -1, (5, 5), normalize=False)
new_image = show_multi_imgs(4, [img, img2, img3], (1, 3))
cv2.namedWindow('img&img2&img3', 0)
cv2.imshow('img&img2&img3', new_image)
cv2.waitKey(0)

运行代码显示如下:

blur():均值滤波

函数原型

    方盒滤波的参数为True时,就是均值滤波,所以这个API用的不多。
    dst = cv2.blur(scr, ksize, anchor, borderType)
   

    scr:源图像
    kernel:卷积核大小(x,y)
    anchor:锚点
    borderType:有映射类型,加一个黑边,默认不设置

2.3  低通滤波GaussianBlur:高斯滤波(去高斯噪音)

适用于有高斯噪点的图片,函数原型:

dst = cv2.GaussianBlur(img, ksize, sigmaX, sigmaY, …)

img:输入的图像
ksize:卷积核大小
sigmaX:表示高斯核函数在X方向的的标准偏差。
sigmaY:表示高斯核函数在Y方向的的标准偏差。

重点关注前三个参数

示例代码:

import cv2
import numpy as np# 一个窗口显示多张图片
def show_multi_imgs(scale, imglist, order=None, border=10, border_color=(255, 255, 0)):""":param scale: float 原图缩放的尺度:param imglist: list 待显示的图像序列:param order: list or tuple 显示顺序 行×列:param border: int 图像间隔距离:param border_color: tuple 间隔区域颜色:return: 返回拼接好的numpy数组"""if order is None:order = [1, len(imglist)]allimgs = imglist.copy()ws , hs = [], []for i, img in enumerate(allimgs):if np.ndim(img) == 2:allimgs[i] = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)allimgs[i] = cv2.resize(img, dsize=(0, 0), fx=scale, fy=scale)ws.append(allimgs[i].shape[1])hs.append(allimgs[i].shape[0])w = max(ws)h = max(hs)# 将待显示图片拼接起来sub = int(order[0] * order[1] - len(imglist))# 判断输入的显示格式与待显示图像数量的大小关系if sub > 0:for s in range(sub):allimgs.append(np.zeros_like(allimgs[0]))elif sub < 0:allimgs = allimgs[:sub]imgblank = np.zeros(((h+border) * order[0], (w+border) * order[1], 3)) + border_colorimgblank = imgblank.astype(np.uint8)for i in range(order[0]):for j in range(order[1]):imgblank[(i * h + i*border):((i + 1) * h+i*border), (j * w + j*border):((j + 1) * w + j*border), :] = allimgs[i * order[1] + j]return imgblankimg = cv2.imread('../data/gauss2.jpeg')# 高斯去噪
img2 = cv2.GaussianBlur(img, (3, 3), 0)new_image = show_multi_imgs(4, [img, img2], (1, 2))
cv2.namedWindow('img&img2', 0)
cv2.imshow('img&img2', new_image)
cv2.waitKey(0)

运行代码显示如下:

2.4 低通滤波medianBlur:中值滤波(去胡椒噪音)

函数原型:

对胡椒噪音去噪明显,取中间的值作为卷积结果

dst = cv2.medianBlur(img, ksize)

img:输入图像
ksize:卷积核大小一个数字

示例代码:

import cv2
import numpy as np# 一个窗口显示多张图片
def show_multi_imgs(scale, imglist, order=None, border=10, border_color=(255, 255, 0)):""":param scale: float 原图缩放的尺度:param imglist: list 待显示的图像序列:param order: list or tuple 显示顺序 行×列:param border: int 图像间隔距离:param border_color: tuple 间隔区域颜色:return: 返回拼接好的numpy数组"""if order is None:order = [1, len(imglist)]allimgs = imglist.copy()ws , hs = [], []for i, img in enumerate(allimgs):if np.ndim(img) == 2:allimgs[i] = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)allimgs[i] = cv2.resize(img, dsize=(0, 0), fx=scale, fy=scale)ws.append(allimgs[i].shape[1])hs.append(allimgs[i].shape[0])w = max(ws)h = max(hs)# 将待显示图片拼接起来sub = int(order[0] * order[1] - len(imglist))# 判断输入的显示格式与待显示图像数量的大小关系if sub > 0:for s in range(sub):allimgs.append(np.zeros_like(allimgs[0]))elif sub < 0:allimgs = allimgs[:sub]imgblank = np.zeros(((h+border) * order[0], (w+border) * order[1], 3)) + border_colorimgblank = imgblank.astype(np.uint8)for i in range(order[0]):for j in range(order[1]):imgblank[(i * h + i*border):((i + 1) * h+i*border), (j * w + j*border):((j + 1) * w + j*border), :] = allimgs[i * order[1] + j]return imgblankimg = cv2.imread('../data/girl01.jpg')# 高斯去噪
img2 = cv2.medianBlur(img, 5)new_image = show_multi_imgs(4, [img, img2], (1, 2))
cv2.namedWindow('img&img2', 0)
cv2.imshow('img&img2', new_image)
cv2.waitKey(0)

运行代码显示如下:

2.5 低通滤波bilateralFilter:双边滤波

函数原型

双边滤波的主要应用场景是视频美颜

cv2.bilateralFilter(img, d, sigmaColor, sigmaSpace, …)

img:输入图像
d:直径,与卷积核中心点的距离,一般取5
sigmaColor:颜色空间滤波器的sigma值。这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
sigmaSpace:sigmaSpace坐标空间中滤波器的sigma值,坐标空间的标注方差。他的数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。当d>0,d指定了邻域大小且与sigmaSpace无关。否则,d正比于sigmaSpace。
 

双边滤波的作用::图像去噪保边,对相关分析的结果有较大的影响,对于裂缝比较强,噪声比较少的图像来说,可以将去噪的程度放大,对以后的相关分析的结果就会有更少的噪声。对于噪声不是很集中的图像,并有较多细节的图像,增加保边的效果,让相关分析及后续进行进一步的结构处理,去噪。

示例代码:

import cv2
import numpy as np# 一个窗口显示多张图片
def show_multi_imgs(scale, imglist, order=None, border=10, border_color=(255, 255, 0)):""":param scale: float 原图缩放的尺度:param imglist: list 待显示的图像序列:param order: list or tuple 显示顺序 行×列:param border: int 图像间隔距离:param border_color: tuple 间隔区域颜色:return: 返回拼接好的numpy数组"""if order is None:order = [1, len(imglist)]allimgs = imglist.copy()ws , hs = [], []for i, img in enumerate(allimgs):if np.ndim(img) == 2:allimgs[i] = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)allimgs[i] = cv2.resize(img, dsize=(0, 0), fx=scale, fy=scale)ws.append(allimgs[i].shape[1])hs.append(allimgs[i].shape[0])w = max(ws)h = max(hs)# 将待显示图片拼接起来sub = int(order[0] * order[1] - len(imglist))# 判断输入的显示格式与待显示图像数量的大小关系if sub > 0:for s in range(sub):allimgs.append(np.zeros_like(allimgs[0]))elif sub < 0:allimgs = allimgs[:sub]imgblank = np.zeros(((h+border) * order[0], (w+border) * order[1], 3)) + border_colorimgblank = imgblank.astype(np.uint8)for i in range(order[0]):for j in range(order[1]):imgblank[(i * h + i*border):((i + 1) * h+i*border), (j * w + j*border):((j + 1) * w + j*border), :] = allimgs[i * order[1] + j]return imgblankimg = cv2.imread('../data/biteral.jpg')# 双边滤波
img2 = cv2.bilateralFilter(img, 5, 20, 50)new_image = show_multi_imgs(4, [img, img2], (1, 2))
cv2.namedWindow('img&img2', 0)
cv2.imshow('img&img2', new_image)
cv2.waitKey(0)

运行代码显示如下:

2.6 高通滤波Sobel

只能一次在x方向上或者y方向上求导,然后把结果相加。

dst1 = cv2.Sobel(src, ddepth, dx, dy, ksize = 3, scale = 1, delta = 0, borderType = BORDER_DEFAULT )

src:输入原图像
ddepth:位深,默认为-1
dx,dy:只能选择一个方向上要么0、1,要么1、0
ksize:卷积核大小,默认为3,当-1时为沙尔
scale:缩放大小,一般就用默认值
delta:偏移量,一般就用默认值
borderType:边界扩充类型,一般就用默认值
 

 示例代码:

import cv2
import numpy as np# 一个窗口显示多张图片
def show_multi_imgs(scale, imglist, order=None, border=10, border_color=(255, 255, 0)):""":param scale: float 原图缩放的尺度:param imglist: list 待显示的图像序列:param order: list or tuple 显示顺序 行×列:param border: int 图像间隔距离:param border_color: tuple 间隔区域颜色:return: 返回拼接好的numpy数组"""if order is None:order = [1, len(imglist)]allimgs = imglist.copy()ws , hs = [], []for i, img in enumerate(allimgs):if np.ndim(img) == 2:allimgs[i] = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)allimgs[i] = cv2.resize(img, dsize=(0, 0), fx=scale, fy=scale)ws.append(allimgs[i].shape[1])hs.append(allimgs[i].shape[0])w = max(ws)h = max(hs)# 将待显示图片拼接起来sub = int(order[0] * order[1] - len(imglist))# 判断输入的显示格式与待显示图像数量的大小关系if sub > 0:for s in range(sub):allimgs.append(np.zeros_like(allimgs[0]))elif sub < 0:allimgs = allimgs[:sub]imgblank = np.zeros(((h+border) * order[0], (w+border) * order[1], 3)) + border_colorimgblank = imgblank.astype(np.uint8)for i in range(order[0]):for j in range(order[1]):imgblank[(i * h + i*border):((i + 1) * h+i*border), (j * w + j*border):((j + 1) * w + j*border), :] = allimgs[i * order[1] + j]return imgblankimg = cv2.imread('../data/biteral.jpg')# Sobel
dx = cv2.Sobel(img, -1, 1, 0, ksize=3)
dy = cv2.Sobel(img, -1, 0, 1, ksize=3)# dst = dx+dy
dst = cv2.add(dx, dy)new_image = show_multi_imgs(4, [img, dx, dy, dst], (1, 4))
cv2.namedWindow('img1-4', 0)
cv2.imshow('img1-4', new_image)
cv2.waitKey(0)

运行代码显示如下:

一幅图的边缘被很好的分割出来。

2.7 高通滤波Scharr

与Sobel类似,只不过使用的ksize值不同,Scharr不能改变卷积核的大小,只能是3*3的。同样只能求一个方向上的边缘。

cv2.Scharr(src, ddepth, dx, dy, scale = 1, delta = 0, borderType = BORDER_DEFAULT).
src:输入原图像
ddepth:位深,默认为-1
dx,dy:只能选择一个方向上要么0、1,要么1、0
scale:缩放大小,一般就用默认值
delta:偏移量,一般就用默认值
borderType:边界扩充类型,一般就用默认值

示例代码:

import cv2
import numpy as np# 一个窗口显示多张图片
def show_multi_imgs(scale, imglist, order=None, border=10, border_color=(255, 255, 0)):""":param scale: float 原图缩放的尺度:param imglist: list 待显示的图像序列:param order: list or tuple 显示顺序 行×列:param border: int 图像间隔距离:param border_color: tuple 间隔区域颜色:return: 返回拼接好的numpy数组"""if order is None:order = [1, len(imglist)]allimgs = imglist.copy()ws , hs = [], []for i, img in enumerate(allimgs):if np.ndim(img) == 2:allimgs[i] = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)allimgs[i] = cv2.resize(img, dsize=(0, 0), fx=scale, fy=scale)ws.append(allimgs[i].shape[1])hs.append(allimgs[i].shape[0])w = max(ws)h = max(hs)# 将待显示图片拼接起来sub = int(order[0] * order[1] - len(imglist))# 判断输入的显示格式与待显示图像数量的大小关系if sub > 0:for s in range(sub):allimgs.append(np.zeros_like(allimgs[0]))elif sub < 0:allimgs = allimgs[:sub]imgblank = np.zeros(((h+border) * order[0], (w+border) * order[1], 3)) + border_colorimgblank = imgblank.astype(np.uint8)for i in range(order[0]):for j in range(order[1]):imgblank[(i * h + i*border):((i + 1) * h+i*border), (j * w + j*border):((j + 1) * w + j*border), :] = allimgs[i * order[1] + j]return imgblankimg = cv2.imread('../data/biteral.jpg')# Sobel,当ksize=-1时,就是Scharr
# dx = cv2.Sobel(img, -1, 1, 0, ksize=-1)
# dy = cv2.Sobel(img, -1, 0, 1, ksize=-1)dx = cv2.Scharr(img, -1, 1, 0)
dy = cv2.Scharr(img, -1, 0, 1)# dst = dx+dy
dst = cv2.add(dx,dy)new_image = show_multi_imgs(4, [img, dx, dy, dst], (1, 4))
cv2.namedWindow('img1-4', 0)
cv2.imshow('img1-4', new_image)
cv2.waitKey(0)

运行代码显示如下:

2.8 高通滤波Laplacian(拉普拉斯)

Laplacian可以同时求两个方向上的边缘,但是对噪音比较敏感,一般需要先进行去噪再调用Laplacian。

dst = cv2.Laplacian(src, ddepth, ksize = 1 ,scale = 1, borderType = BORDER_DEFAULT)

src:输入原图像
ddepth:位深,默认为-1
ksize:卷积核大小,默认为1
scale:缩放大小,一般就用默认值
delta:偏移量,一般就用默认值
borderType:边界扩充类型,一般就用默认值

示例代码:

import cv2
import numpy as np# 一个窗口显示多张图片
def show_multi_imgs(scale, imglist, order=None, border=10, border_color=(255, 255, 0)):""":param scale: float 原图缩放的尺度:param imglist: list 待显示的图像序列:param order: list or tuple 显示顺序 行×列:param border: int 图像间隔距离:param border_color: tuple 间隔区域颜色:return: 返回拼接好的numpy数组"""if order is None:order = [1, len(imglist)]allimgs = imglist.copy()ws , hs = [], []for i, img in enumerate(allimgs):if np.ndim(img) == 2:allimgs[i] = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)allimgs[i] = cv2.resize(img, dsize=(0, 0), fx=scale, fy=scale)ws.append(allimgs[i].shape[1])hs.append(allimgs[i].shape[0])w = max(ws)h = max(hs)# 将待显示图片拼接起来sub = int(order[0] * order[1] - len(imglist))# 判断输入的显示格式与待显示图像数量的大小关系if sub > 0:for s in range(sub):allimgs.append(np.zeros_like(allimgs[0]))elif sub < 0:allimgs = allimgs[:sub]imgblank = np.zeros(((h+border) * order[0], (w+border) * order[1], 3)) + border_colorimgblank = imgblank.astype(np.uint8)for i in range(order[0]):for j in range(order[1]):imgblank[(i * h + i*border):((i + 1) * h+i*border), (j * w + j*border):((j + 1) * w + j*border), :] = allimgs[i * order[1] + j]return imgblankimg = cv2.imread('../data/biteral.jpg')dst = cv2.Laplacian(img, -1, ksize=5)
new_image = show_multi_imgs(4, [img, dst], (1, 2))
cv2.namedWindow('img&dst', 0)
cv2.imshow('img&dst', new_image)
cv2.waitKey(0)

卷积核大小为5*5的结果

运行代码结果显示:

2.8 高通滤波Canny

使用5*5高斯滤波消除噪声,可以计算图像的四个方向上的边缘(0,45,90,135),取局部的最大值,多了一个阈值计算。高于阈值我们认为是边缘,低于阈值就不是边缘,显然A为边缘,如果,但是B和C介于最大值最小值之间,BC既不是边缘也是边缘,但是C与A在一条直线上,所以C也是边缘。

dst = cv2.Canny(img, minVal, maxVal)

img:原图像
minVal:最小阈值
maxVal:最大阈值
低于最小阈值就不是边缘,高于最大阈值是边缘。 

示例代码:

import cv2
import numpy as np# 一个窗口显示多张图片
def show_multi_imgs(scale, imglist, order=None, border=10, border_color=(255, 255, 0)):""":param scale: float 原图缩放的尺度:param imglist: list 待显示的图像序列:param order: list or tuple 显示顺序 行×列:param border: int 图像间隔距离:param border_color: tuple 间隔区域颜色:return: 返回拼接好的numpy数组"""if order is None:order = [1, len(imglist)]allimgs = imglist.copy()ws , hs = [], []for i, img in enumerate(allimgs):if np.ndim(img) == 2:allimgs[i] = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)allimgs[i] = cv2.resize(img, dsize=(0, 0), fx=scale, fy=scale)ws.append(allimgs[i].shape[1])hs.append(allimgs[i].shape[0])w = max(ws)h = max(hs)# 将待显示图片拼接起来sub = int(order[0] * order[1] - len(imglist))# 判断输入的显示格式与待显示图像数量的大小关系if sub > 0:for s in range(sub):allimgs.append(np.zeros_like(allimgs[0]))elif sub < 0:allimgs = allimgs[:sub]imgblank = np.zeros(((h+border) * order[0], (w+border) * order[1], 3)) + border_colorimgblank = imgblank.astype(np.uint8)for i in range(order[0]):for j in range(order[1]):imgblank[(i * h + i*border):((i + 1) * h+i*border), (j * w + j*border):((j + 1) * w + j*border), :] = allimgs[i * order[1] + j]return imgblankimg = cv2.imread('../data/biteral.jpg')# canny
dst = cv2.Canny(img, 100, 200)
dst = cv2.cvtColor(dst, cv2.COLOR_GRAY2BGR)new_image = show_multi_imgs(4, [img, dst], (1, 2))
cv2.namedWindow('img&dst', 0)
cv2.imshow('img&dst', new_image)
cv2.waitKey(0)

运行代码显示如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/206884.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

R语言实现Lasso回归

一、Lasso回归 Lasso 回归&#xff08;Least Absolute Shrinkage and Selection Operator Regression&#xff09;是一种用于线性回归和特征选择的统计方法。它在回归问题中加入了L1正则化项&#xff0c;有助于解决多重共线性&#xff08;多个特征高度相关&#xff09;和特征选…

C语言——写一个简单函数,找两个数中最大者

#include <stdio.h>int max( int a, int b ) { return a>b ? a:b; }int main() { int a, b;printf("输入两个数:\n");scanf("%d %d", &a, &b);printf("max %d\n", max(a, b));return 0; }输出结果&#xff1a;

C#文件基本操作(判断文件是否存在、创建文件、复制或移动文件、删除文件以及获取文件基本信息)

目录 一、判断文件是否存在 1.File类的Exists()方法 2.FileInfo类的Exists属性 二、创建文件 1.File类的Create()方法 2.FileInfo类的Create()方法 三、复制或移动文件 1.File类的Copy()方法 2.File类的Move()方法 3.FileInfo类的CopyTo()方法 四、删除文件 1.File…

大数据基础设施搭建 - Hive

文章目录 一、上传压缩包二、解压压缩包三、配置环境变量四、初始化元数据库4.1 配置MySQL地址4.2 拷贝MySQL驱动4.3 初始化元数据库4.3.1 创建数据库4.3.2 初始化元数据库 五、启动元数据服务metastore5.1 修改配置文件5.2 启动/关闭metastore服务 六、启动hiveserver2服务6.1…

MacOS + Android Studio 通过 USB 数据线真机调试

环境&#xff1a;Apple M1 MacOS Sonoma 14.1.1 软件&#xff1a;Android Studio Giraffe | 2022.3.1 Patch 3 设备&#xff1a;小米10 Android 13 一、创建测试项目 安卓 HelloWorld 项目: 安卓 HelloWorld 项目 二、数据线连接手机 1. 手机开启开发者模式 参考&#xff1…

FFmpeg之将视频转为16:9(横屏)或9:16(竖屏)(一)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

代码随想录算法训练营第一天 | 704. 二分查找 27. 移除元素

class Solution { public:int search(vector<int>& nums, int target) {int l0;int rnums.size()-1;while(l<r){int mid(lr)>>1;if(targetnums[mid]) return mid;if(target>nums[mid]){lmid1;}else{rmid-1;}}return -1;} }; 之前就已经熟悉二分法了&am…

【HuggingFace Transformer库学习笔记】基础组件学习:pipeline

一、Transformer基础知识 pip install transformers datasets evaluate peft accelerate gradio optimum sentencepiece pip install jupyterlab scikit-learn pandas matplotlib tensorboard nltk rouge在host文件里添加途中信息&#xff0c;可以避免运行代码下载模型时候报错…

计算机网络(二)

&#xff08;八&#xff09;客户端软件设计的细节 A、解析协议号 客户端可能会需要通过协议名指定协议&#xff0c;但是Socket接口是用协议号指定的&#xff0c;这时候我们就需要使用getprotobyname()函数实现协议名到协议号的转换&#xff0c;该函数会返回一个指向protoent的…

西南科技大学电路分析基础实验A1(元件伏安特性测试 )

目录 一、实验目的 二、实验设备 三、预习内容(如:基本原理、电路图、计算值等) 1、测定线性电阻的伏安特性 2、二极管伏安特性测试 3、测定实际电压源的伏安特性 四、实验数据及结果分析(预习写必要实验步骤和表格) 1、测定线性电阻的伏安特性 2、二极管伏安特性测…

Redis未授权访问-CNVD-2019-21763复现

Redis未授权访问-CNVD-2019-21763复现 利用项目&#xff1a; https://github.com/vulhub/redis-rogue-getshell 解压后先进入到 RedisModulesSDK目录里面的exp目录下&#xff0c;make编译一下才会产生exp.so文件&#xff0c;后面再利用这个exp.so文件进行远程代码执行 需要p…

能耗远程在线监测系统在工业节能提高效率

摘要&#xff1a;为保证企业实现节能减排目标&#xff0c;设计和使用远程在线监测系统势在必行。远程在线监测系统是基于传感器与网络技术的优势&#xff0c;在企业区域各个位置针对性安装传感器&#xff0c;对实时数据进行采集、编码传输到远程管理系统。远程管理系统对采集的…

系统设计面试指南之分布式任务调度

1 简介 任务是需要资源(CPU 时间、内存、存储、网络带宽等)在指定时间内完成的一段计算工作。 通过智能地将资源分配给任务以满足任务级和系统级目标的系统称为任务调度程序。 任务调度程序&#xff1a; 及时决定和分配资源给任务的过程称为任务调度。 当我们在 Facebook 发…

【EasyExcel】导出excel并支持自定义设置数据行背景颜色等

需求背景&#xff1a; 根据查询条件将列表数据导出&#xff0c;并筛选出满足某个条件的数据&#xff0c;将满足条件的数据的背景颜色设置成黄色。 &#xff08;本文例子如&#xff1a;name出现的次数大于等于2&#xff0c;将相关数据背景颜色都设置为黄色&#xff09; …

MySQL备份与恢复(重点)

MySQL备份与恢复&#xff08;重点&#xff09; 一、用户管理与权限管理 ☆ 用户管理 1、创建MySQL用户 注意&#xff1a;MySQL中不能单纯通过用户名来说明用户&#xff0c;必须要加上主机。如jack10.1.1.1 基本语法&#xff1a; mysql> create user 用户名被允许连接的主…

java springboot测试类虚拟MVC环境 匹配返回值与预期内容是否相同 (JSON数据格式) 版

上文java springboot测试类鉴定虚拟MVC请求 返回内容与预期值是否相同我们讲了测试类中 虚拟MVC发送请求 匹配返回内容是否与预期值相同 但是 让我意外的是 既然没人骂我 因为我们实际开发 返回的基本都是json数据 字符串的接口场景是少数的 我们在java文件目录下创建一个 dom…

3分钟使用 WebSocket 搭建属于自己的聊天室(WebSocket 原理、应用解析)

文章目录 WebSocket 的由来WebSocket 是什么WebSocket 优缺点优点缺点 WebSocket 适用场景主流浏览器对 WebSocket 的兼容性WebSocket 通信过程以及原理建立连接具体过程示例Sec-WebSocket-KeySec-WebSocket-Extensions 数据通信数据帧帧头&#xff08;Frame Header&#xff09…

Spring整合web环境

目录 Javaweb三大组件及环境特点 Spring整合web环境的思路及实现 Spring的web开发组件spring-web MVC框架思想及其设计思路 Javaweb三大组件及环境特点 Spring整合web环境的思路及实现 package com.xfy.listener;import com.xfy.config.SpringConfig; import org.springfra…

具备这四个特征的项目经理,牛逼!

大家好&#xff0c;我是老原。 成为一个业绩第一又能准时下班的工作强人&#xff0c;应该是每个职场人的梦想&#xff0c;但现实往往不那么尽如人意…… 虽然如此&#xff0c;但是不代表我们不能向能做到这样的大佬看齐啊。 工作十余年&#xff0c;见过各种各样的职场人士&a…

高级IO select 多路转接实现思路

文章目录 select 函数fd_set 类型timeval 结构体select 函数的基本使用流程文件描述符就绪条件以select函数为中心实现多路转接的思路select 缺陷 select 函数 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); selec…