当前位置: 首页 > news >正文

OpenCV2-图像基本操作-阈值与平滑处理-形态学-梯度运算

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 1. 图像基本操作
    • 1.0 基本操作
    • 1.1 视频的读取与处理
    • 1.2 截取部分图像数据
    • 1.3 颜色通道提取
    • 1.4 边界填充
    • 1.5 数值计算
    • 1.6 图像融合
  • 2. 阈值与平滑处理
    • 2.1 图像阈值
    • 2.2 图像平滑
    • 2.3 高斯与中值滤波
  • 3. 图像形态学操作
    • 3.1 形态学-腐蚀操作
    • 3.2 形态学-膨胀操作
    • 3.3 开运算与闭运算
    • 3.4 梯度运算
    • 3.5 礼帽与黑帽
  • 4. 图像梯度运算
    • 4.1 图像梯度-Sobel算子
    • 4.2 图像梯度-Scharr算子和laplacian算子
  • 总结


前言

1. 图像基本操作

1.0 基本操作

在这里插入图片描述

import cv2 #opencv读取的格式是BGR
import matplotlib.pyplot as plt
import numpy as np 
%matplotlib inlineimg=cv2.imread('../cat.jpg')

%matplotlib inline 是一个特殊的 IPython 魔法命令
执行该命令后,后续所有 plt.plot()、plt.imshow() 等绘图命令的结果会直接显示在代码单元格的下方
图像会被保存为静态图片嵌入到笔记本中,方便保存和分享
不需要再额外调用 plt.show() 来显示图像(不过调用了也不会有问题)

在这里插入图片描述

#图像的显示,也可以创建多个窗口
cv2.imshow('image',img) 
# 等待时间,毫秒级,0表示任意键终止
cv2.waitKey(10000) 
cv2.destroyAllWindows()

过了十秒,弹窗就自动消失了

在这里插入图片描述

def cv_show(name,img):cv2.imshow(name,img) cv2.waitKey(0) cv2.destroyAllWindows()

创建了一个自动显示的函数

在这里插入图片描述

img=cv2.imread('../img/cat.jpg',cv2.IMREAD_GRAYSCALE)
img

在这里插入图片描述
这个是以灰度图的形式展示

#图像的显示,也可以创建多个窗口
cv2.imshow('image',img) 
# 等待时间,毫秒级,0表示任意键终止
cv2.waitKey(10000) 
cv2.destroyAllWindows()

在这里插入图片描述

#保存
cv2.imwrite('mycat.png',img)

在这里插入图片描述
在这里插入图片描述

type(img)
img.size
img.dtype

在这里插入图片描述

1.1 视频的读取与处理

视频也是由图片组成的
每一帧都是一个静止的图像,这样就可以了
每s30帧,就是一秒30张图—》我们正常人类就看不出来是卡的
每秒15帧,图片之间的间隔比较大–》比较卡,看着

把视频拆分为每一帧就可以操作了

vc = cv2.VideoCapture('../img/test.mp4')
# 检查是否打开正确
if vc.isOpened(): open, frame = vc.read()
else:open = False

vc.read()就是读取第一帧
然后就是第二帧,一直读取
这一帧读取成功了,那么oepn就是true
frame 就是这一帧的图像数据

vc.read() 是读取一帧图像的方法
返回两个值:
open(布尔值):表示是否成功读取到帧
frame(numpy 数组):读取到的图像帧数据(BGR 格式)
这行代码的作用是尝试从设备中读取第一帧图像

while open:ret, frame = vc.read()if frame is None:breakif ret == True:gray = cv2.cvtColor(frame,  cv2.COLOR_BGR2GRAY)cv2.imshow('result', gray)if cv2.waitKey(10) & 0xFF == 27:break
vc.release()
cv2.destroyAllWindows()

gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
将彩色帧(BGR 格式)转为灰度图

cv2.imshow(‘result’, gray)
在名为 result 的窗口中显示灰度图

if cv2.waitKey(10) & 0xFF == 27:
等待 10 毫秒,检测键盘输入
27 是 ASCII 码,对应键盘上的 Esc 键
break
如果按下 Esc 键,退出循环
vc.release()
释放视频捕获设备资源(如摄像头)
cv2.destroyAllWindows()
关闭所有 OpenCV 创建的窗口

循环读取视频帧 → 转为灰度图 → 显示图像 → 检测到 Esc 键或无有效帧时退出 → 释放资源

cv2.waitKey(10)
这是 OpenCV 的键盘输入等待函数。
参数 10 表示等待 10 毫秒(单位:毫秒)。在这段时间内,如果用户按下任何键,函数会返回该键的 ASCII 码;如果没有按键,返回 -1。
作用:给系统留出时间处理窗口事件(比如显示图像),同时检测键盘输入。
& 0xFF
这是一个位运算,用于提取按键值的低 8 位(即 0-255 的范围)。
因为 cv2.waitKey() 的返回值在不同系统上可能是 32 位整数(高 24 位可能包含其他信息),通过与 0xFF(二进制 11111111)做与运算,可以确保只保留有效的 ASCII 码部分。
== 27
27 是 ASCII 码中对应的 Esc 键(Escape 键)。
整个条件的意思是:如果用户在 10 毫秒内按下了 Esc 键,则条件成立。

每次都会在这里等10ms

在这里插入图片描述

这样就变成了灰度视频了

        if cv2.waitKey(100) & 0xFF == 27:

如果是这样的话,就很慢了

1.2 截取部分图像数据

#截取部分图像数据
img=cv2.imread('../img/cat.jpg')
cat=img[0:200,0:200] 
cv_show('cat',cat)

在这里插入图片描述

1.3 颜色通道提取

b,g,r=cv2.split(img)

在这里插入图片描述
在这里插入图片描述

img=cv2.merge((b,g,r))
img.shape

这样就可以1组合起来了

# 只保留R
cur_img = img.copy()
#bgr,所以b的索引为0
cur_img[:,:,0] = 0
cur_img[:,:,1] = 0
cv_show('R',cur_img)

在这里插入图片描述

这样就是只有R了

# 只保留G
cur_img = img.copy()
cur_img[:,:,0] = 0
cur_img[:,:,2] = 0
cv_show('G',cur_img)

在这里插入图片描述

1.4 边界填充

在这里插入图片描述

在这里插入图片描述

#上下左右分别填充的大小
top_size,bottom_size,left_size,right_size = (50,50,50,50)replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_CONSTANT, value=0)

只是后面的填充方法不一样而已

import matplotlib.pyplot as plt
plt.subplot(231), plt.imshow(img, 'gray'), plt.title('ORIGINAL')
plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('REPLICATE')
plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title('REFLECT')
plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101')
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP')
plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT')plt.show()

plt.subplot(231) 是 Matplotlib 中用于创建子图的函数,其参数 231 是一个三位数的缩写,具体含义如下:
第一位数字 2 表示行数:整个图像区域将被分成 2 行
第二位数字 3 表示列数:整个图像区域将被分成 3 列
第三位数字 1 表示位置索引:当前子图位于第 1 个位置

在这里插入图片描述

BORDER_REPLICATE:复制法,也就是复制最边缘像素。
BORDER_REFLECT:反射法,对感兴趣的图像中的像素在两边进行复制例如:fedcba|abcdefgh|hgfedcb
BORDER_REFLECT_101:反射法,也就是以最边缘像素为轴,对称,gfedcb|abcdefgh|gfedcba
BORDER_WRAP:外包装法cdefgh|abcdefgh|abcdefg
BORDER_CONSTANT:常量法,常数值填充。

第一个是原图

1.5 数值计算

img_cat=cv2.imread('../img/cat.jpg')
img_dog=cv2.imread('../img/dog.jpg')
img_cat2= img_cat +10 
img_cat[:5,:,0]

加法就是在每一个位置上都加上10

在这里插入图片描述

#相当于% 256
(img_cat + img_cat2)[:5,:,0] 

在这里插入图片描述

142+152=294
294%256=38

cv2.add(img_cat,img_cat2)[:5,:,0]

在这里插入图片描述
142+152=294~~255

1.6 图像融合

img_cat + img_dog

这样是不行的额,因为行列不一样
在这里插入图片描述
我们把它们变为一样的

img_dog = cv2.resize(img_dog, (500, 414))
img_dog.shape

在这里插入图片描述

res = cv2.resize(img, (0, 0), fx=3, fy=1)
plt.imshow(res)

(0, 0) 是 dsize 参数的值,表示不直接指定输出图像的尺寸,而是通过后面的缩放因子 fx 和 fy 来计算新尺寸
fx=3 表示水平方向放大 3 倍
fy=1 表示垂直方向保持原尺寸不变
在这里插入图片描述

res = cv2.addWeighted(img_cat, 0.4, img_dog, 0.6, 0)

这个表示按照权值相加
但是前提肯定是长宽相同

plt.imshow(res)
plt.show()

在这里插入图片描述

2. 阈值与平滑处理

2.1 图像阈值

ret, dst = cv2.threshold(src, thresh, maxval, type)
src: 输入图,只能输入单通道图像,通常来说为灰度图dst: 输出图thresh: 阈值maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值type:二值化操作的类型,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INVcv2.THRESH_BINARY           超过阈值部分取maxval(最大值),否则取0cv2.THRESH_BINARY_INV    THRESH_BINARY的反转cv2.THRESH_TRUNC            大于阈值部分设为阈值,否则不变cv2.THRESH_TOZERO          大于阈值部分不改变,否则设为0cv2.THRESH_TOZERO_INV  THRESH_TOZERO的反转
ret, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]for i in range(6):plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')plt.title(titles[i])plt.xticks([]), plt.yticks([])
plt.show()

THRESH_BINARY表示当前像素点大于127的话,那么就赋值为255,大于127,有点亮,255就超级亮–》白点
小于阈值就取0—》黑点,黑的全为黑了

thresh1 是图像的值,ret是阈值
在这里插入图片描述
THRESH_BINARY_INV 中INV表示反转

2.2 图像平滑

#%% md
![image.png](attachment:image.png)
#%%
img = cv2.imread('../img/lenaNoise.png')cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

有些白点—》去掉

在这里插入图片描述

我们这里要用到均值滤波,意思就是把204变为周围3*3的平均值,每个值都这样处理
在这里插入图片描述

怎么计算呢,我们可以把这个33的矩阵去乘以33的全1矩阵

# 均值滤波
# 简单的平均卷积操作
blur = cv2.blur(img, (3, 3))cv2.imshow('blur', blur)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
发现白点没有那么明显了

# 方框滤波
# 基本和均值一样,可以选择归一化
box = cv2.boxFilter(img,-1,(3,3), normalize=True)  cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()

参数 -1 表示输出图像的深度(即像素值的数据类型)与输入图像保持一致。

当 normalize=True 时,滤波核(方框)内所有像素的权重会被平均化(总和为 1)。计算方式是:将方框内所有像素值相加后,再除以方框内像素的总数量(即方框面积),这样可以保证输出像素值不会超出原图像的像素值范围。
如果设置 normalize=False,则不进行归一化,此时计算方式只是简单地将方框内所有像素值相加。这种情况下,如果方框较大,可能会导致像素值超过最大值(如 255),从而出现图像过曝(白块)现象。
在这里插入图片描述

所以得到的结果和均值滤波一样

# 方框滤波
# 基本和均值一样,可以选择归一化
box = cv2.boxFilter(img,-1,(3,3), normalize=False)cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

False就没有除以9了,直接超级白了

2.3 高斯与中值滤波

在这里插入图片描述
高斯滤波就是这样的,近的就占的比重大点

# 高斯滤波
# 高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的
aussian = cv2.GaussianBlur(img, (5, 5), 1)  cv2.imshow('aussian', aussian)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

中值滤波就是3*3数字排完序之后,取中间的值

# 中值滤波
# 相当于用中值代替
median = cv2.medianBlur(img, 5)  # 中值滤波cv2.imshow('median', median)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
5表示5*5

基本上都不见了

因为噪音点少,而且噪音点比较亮,值比较大,所以排序选中间一般可能选不到它
但是取平均的话,很有可能就会偏亮,因为噪音点值大

# 展示所有的
res = np.hstack((blur,aussian,median))
print (res)
cv2.imshow('median vs average', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

这个就是图像拼接,hstack表示横着拼接

在这里插入图片描述

vstack表示竖着拼接

3. 图像形态学操作

3.1 形态学-腐蚀操作

img = cv2.imread('../img/dige.png')cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

这就是图像操作的前提,图像数据是二值的

意思就是只有两种颜色
怎么去掉那些虚线呢–》腐蚀操作

pie = cv2.imread('../img/pie.png')cv2.imshow('pie', pie)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

在这里插入图片描述

腐蚀操作意思就是当一个点的3*3范围内的时候,有两种颜色----》这个点就腐蚀掉-----》置于黑色
----》就会变小了,这个圆
腐蚀而且还有迭代次数的,每次腐蚀,圆都会变小

kernel = np.ones((3,3),np.uint8) 
erosion = cv2.erode(img,kernel,iterations = 1)cv2.imshow('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

kernel = np.ones((3,3),np.uint8) 
erosion = cv2.erode(img,kernel,iterations = 3)cv2.imshow('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
(3,3)这个区间越大,或者迭代次数越多,那么腐蚀的力度就越大

kernel = np.ones((30,30),np.uint8) 
erosion_1 = cv2.erode(pie,kernel,iterations = 1)
erosion_2 = cv2.erode(pie,kernel,iterations = 2)
erosion_3 = cv2.erode(pie,kernel,iterations = 3)
res = np.hstack((erosion_1,erosion_2,erosion_3))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

3.2 形态学-膨胀操作

这个就是变大了,和腐蚀是相反的效果

kernel = np.ones((3,3),np.uint8) 
dige_erosion = cv2.erode(img,kernel,iterations = 1)cv2.imshow('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
怎么变胖一点呢

kernel = np.ones((3,3),np.uint8) 
dige_dilate = cv2.dilate(dige_erosion,kernel,iterations = 1)cv2.imshow('dilate', dige_dilate)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

就是3*3的时候,有两种颜色的时候,变成白色

pie = cv2.imread('../img/pie.png')kernel = np.ones((30,30),np.uint8) 
dilate_1 = cv2.dilate(pie,kernel,iterations = 1)
dilate_2 = cv2.dilate(pie,kernel,iterations = 2)
dilate_3 = cv2.dilate(pie,kernel,iterations = 3)
res = np.hstack((dilate_1,dilate_2,dilate_3))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

3.3 开运算与闭运算

# 开:先腐蚀,再膨胀
img = cv2.imread('../img/dige.png')kernel = np.ones((5,5),np.uint8) 
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)cv2.imshow('opening', opening)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

# 闭:先膨胀,再腐蚀
img = cv2.imread('../img/dige.png')kernel = np.ones((5,5),np.uint8) 
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)cv2.imshow('closing', closing)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

所以不能去掉毛刺

3.4 梯度运算

# 梯度=膨胀-腐蚀
pie = cv2.imread('../img/pie.png')
kernel = np.ones((7,7),np.uint8) 
dilate = cv2.dilate(pie,kernel,iterations = 5)
erosion = cv2.erode(pie,kernel,iterations = 5)res = np.hstack((dilate,erosion))cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

这个是正常膨胀和腐蚀之后的结果

梯度运算就是膨胀-腐蚀,那么一相减的话,中间那部分相同的部分就变为黑色了

gradient = cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel)cv2.imshow('gradient', gradient)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

3.5 礼帽与黑帽

礼帽 = 原始输入-开运算结果(先腐蚀在膨胀)----》只剩下毛刺了
黑帽 = 闭运算(先膨胀在腐蚀)-原始输入 -----》原始的小轮廓了

#礼帽
img = cv2.imread('../img/dige.png')
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
cv2.imshow('tophat', tophat)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

#黑帽
img = cv2.imread('../img/dige.png')
blackhat  = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT, kernel)
cv2.imshow('blackhat ', blackhat )
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

4. 图像梯度运算

4.1 图像梯度-Sobel算子

img = cv2.imread('../img/pie.png',cv2.IMREAD_GRAYSCALE)
cv2.imshow("img",img)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述

什么是梯度呢,梯度就是一个点上,有不同颜色,就是有梯度—》横着竖着,分别看有没有梯度
在这里插入图片描述

假设我们选的点是p5,然后

咋们的这个矩阵计算呢,就是对应位置相乘的计算,并不是正在的矩阵乘法

所以这个梯度就是右边的值减去左边的,而且近的点,比重大,*2
这样就对比出来了左边与右边的差异—》也就是左右的梯度Gx
竖着的梯度就是下边的减去上边的

dst = cv2.Sobel(src, ddepth, dx, dy, ksize)ddepth:图像的深度,一般是-1就可以了,输出的深度和输入深度一样
dx和dy分别表示水平和竖直方向
ksize是Sobel算子的大小

如果Gx为负数那么就取0,因为这里的颜色数值都是大于等于0的,而且只有32位,只能表示0~255

def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows()
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)cv_show(sobelx,'sobelx')

cv2.CV_64F,使用 64 位浮点型是为了能够表示负数值(
这样梯度为负数的时候,也是直接表示为负数了,不会表示为0了

dx=1,dy-0表示只算水平的梯度,不算竖直的梯度

在这里插入图片描述
因为算的是水平的,是右边减去左边,那么偏左的时候,白色-黑色是大于0,而且是白色,值不变,因为黑色是0
偏右的时候,黑色减去左边小于0,为-255,负数不能显示出来—》截断–》黑色

白到黑是正数,黑到白就是负数了,所有的负数会被截断成0,所以要取绝对值
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
cv_show(sobelx,'sobelx')

convertScaleAbs这个就是取绝对值了,因为CV_64F,所以里面存的是负数,再取绝对值,就对了
在这里插入图片描述

在这里插入图片描述

这个就是总的梯度计算
或者Gx的绝对值+Gy的绝对值

sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)  
cv_show(sobely,'sobely')

在这里插入图片描述

sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv_show(sobelxy,'sobelxy')

就是0.5Gx+0.5Gy了

在这里插入图片描述

sobelxy=cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
sobelxy = cv2.convertScaleAbs(sobelxy) 
cv_show(sobelxy,'sobelxy')

一开始的时候,就一起计算呢

在这里插入图片描述

在这里插入图片描述
所以说这就是为什么东南西北四个方向都没有白点的原因

不建议直接计算

img = cv2.imread('../img/lena.jpg',cv2.IMREAD_GRAYSCALE)
cv_show(img,'img')

在这里插入图片描述
这是一个灰度图

img = cv2.imread('../img/lena.jpg',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv_show(sobelxy,'sobelxy')

在这里插入图片描述
就是找出轮廓的作用了

# 不建议直接计算img = cv2.imread('../img/lena.jpg',cv2.IMREAD_GRAYSCALE)sobelxy=cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
sobelxy = cv2.convertScaleAbs(sobelxy)
cv_show(sobelxy,'sobelxy')

在这里插入图片描述
我们发现直接计算就效果不好了,直接计算会少很多的点

4.2 图像梯度-Scharr算子和laplacian算子

在这里插入图片描述

发现这个差值更大了,但还是右边减去左边,下边减去上边

在这里插入图片描述
这个是中间点和边缘点的差值
如果这个点不在边界-----》变黑
在边界-------》有变化了

#不同算子的差异
img = cv2.imread('../img/lena.jpg',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)   
sobely = cv2.convertScaleAbs(sobely)  
sobelxy =  cv2.addWeighted(sobelx,0.5,sobely,0.5,0)  scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
scharry = cv2.Scharr(img,cv2.CV_64F,0,1)
scharrx = cv2.convertScaleAbs(scharrx)   
scharry = cv2.convertScaleAbs(scharry)  
scharrxy =  cv2.addWeighted(scharrx,0.5,scharry,0.5,0) laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)   res = np.hstack((sobelxy,scharrxy,laplacian))
cv_show(res,'res')

这个就是上面讲的三个算法

在这里插入图片描述

第二个描述得更细节了,你看那木头的纹路都弄出来了
Laplacian描述得一般

总结

http://www.dtcms.com/a/414504.html

相关文章:

  • 【开题答辩全过程】以 springboot+美食电子商城的设计与实现为例,包含答辩的问题和答案
  • MySQL所有关键字详细含义说明
  • MySQL表压缩:用CPU换I/O的秘密武器
  • 做外贸网站需要缴什么税重庆高端网站建设价格
  • java面试day5 | 消息中间件、RabbitMQ、kafka、高可用机制、死信队列、消息不丢失、重复消费
  • 时序数据库选型指南:如何为企业选择合适的时序数据库解决方案
  • 【iOS】alloc、init、new
  • 做网站的开发心得wordpress是不是一定要买服务器
  • AI觉醒:小白的大模型冒险记 第10章:故事续写竞技场 - 实战演练
  • 网站的形成贵州省住房和城乡建设官方网站
  • python知识点
  • LeetCode 5.最长回文字符串
  • 浅谈蓝牙的连接基石
  • Matlab通过GUI实现点云的导向(引导)滤波(附最简版)
  • MacOS - Clang使用bits/stdc++.h - 非官方(竞赛用) - 通用方法
  • 智能进化:高端平板操控系统的技术革新
  • 网站开发专业职业规划微信小程序游戏开发教程
  • 中国工业互联网公司排名seo工程师是什么职业
  • 手机锁屏后WiFi流量/数据流量消耗的深层原因与解决方案
  • 使用 Entity Framework Code First 方法创建 ASP.NET Core 5.0 Web API
  • 网站建设前的分析公司概况了解google seo是什么啊
  • 【C++实战㊾】C++11新特性实战:nullptr与类型推导,解锁编程新姿势
  • Python笔记之Python中的`@`装饰器总结笔记
  • 存储器映射寄存器MMR(Memory-Mapped Register)
  • 【Big Data】DataX 3.0 星型数据链路架构的实践与价值
  • 芯片和半导体:三星发动2nm工艺价格战
  • NLP:讲解Bert模型的变体
  • wordpress成品站源码义乌网站建设九
  • 高通平台WiFi学习--- WLAN 进阶:无需开启 WiFi 也能使用 P2P 功能的实现与探索
  • 【论文笔记】基于深度学习的图像分割研究综述 和 基于深度学习的二分图像分割综述