【OpenCV】基础操作学习--实现原理理解

读取和显示图像

基本操作

  • cv2.imread(filename , flags): 文件中读取图像,从指定路径中读取图像,返回一个图像数组(NumPy数组)
    • filename:图像文件的路径
    • flags:指定读取图像的方式
      • cv2.IMREAD_COLOR(默认为1):以彩色图像读取,忽略透明度通道
      • cv2.IMREAD_GRAYSCALE(0):以灰度图像读取
      • cv2.IMREAD_UNCHANGED(-1):包含图像中alpha通道
  • cv2.imshow():窗口中显示图像,从新窗口中显示图像
  • cv2.waitkey():控制图像显示事件,参数值是毫秒,0表示无限等待
  • 因为运行环境在云服务器上,所以无法实时显示图像,后期补充测试

代码实现1

复制代码
#读取与显示图像
import cv2 

#读取
img = cv2.imread('your_image.jpg')

#检测是否加载成功
if img is None:
    print("图像读取失败,检查图像路径是否存在")
else:
    #显示图像
    cv2.imshow('显示窗口',img)
    #等待任意按键
    cv2.waitKey(0)
    cv2.destroyAllWindows()

代码实现2: 根据三种读取方式,分别读取图片

cpp 复制代码
import cv2

# 读取彩色图像
# color_img = cv2.imread('your_image.jpg', cv2.IMREAD_COLOR)
# cv2.imwrite('color.jpg',color_img)


# 读取灰度图像
# gray_img = cv2.imread('your_image.jpg', cv2.IMREAD_GRAYSCALE)
# cv2.imwrite('gray.jpg',gray_img)


# # 读取包含 alpha 通道的图像
unchanged_img = cv2.imread('your_image.png', cv2.IMREAD_UNCHANGED)
cv2.imwrite('unchange.jpg',unchanged_img)

实现理解

  • **图像读取逻辑:**底层调用图像解码库来读取图像文件,然后将其转换为NumPy数组
  • **图像显示逻辑:**创建一个窗口,然后调用GUI库(例如Qt)将图像数据渲染到屏幕上

计算机图像学相关知识

像素与颜色空间

  • 像素: 图像中的基本元素,通常表示为数值的集合,代表图像在某个位置上的颜色和亮度
    • 图像的最小单位,类似于拼图中的一小块,拼在一起就是一个整体的图像
  • 颜色空间: 描述颜色的模型,使用坐标系或者子空间来表示颜色,例如RGB、BGR、HSV等
    • 不同描述颜色的方法,相似与不同语言但是最终表示的都是相同含义

颜色通道

  • RGB颜色: Red , Green , Blue三个颜色通道组成
    • 每个通道的数值是0-255的整数,相对应着表示颜色强弱
  • BGR颜色: OpenCV默认的颜色模型
    • OpenCV中使用BGR颜色主要是因为需要与早期设计的图形格式兼容
    • 可以通过函数对图片的格式进行变换

像素与图像的理解

cpp 复制代码
import cv2

# 读取彩色图像
img = cv2.imread('your_image.jpg')

# 查看图像的尺寸和像素值
print("图像尺寸:", img.shape)
print("像素值示例:", img[0, 0])  # 输出第一个像素的 BGR 值

# 转换为灰度图像
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
print("灰度图像尺寸:", gray_img.shape)
print("灰度像素值示例:", gray_img[0, 0])  # 输出第一个像素的灰度值

# 保存灰度图像
cv2.imwrite('gray_image.jpg', gray_img)

保存图像

基本操作

  • cv2.imwrite(filename , img , params = None): 将图像保存为文件,也就是将图像保存为指定格式,最终格式取决于设定拓展名
    • **filename:**保存的文件名,其格式是由拓展名决定的
    • **img:**需要保存的图像对象
    • **params:**可选参数,用于设置特定格式的编码参数

代码实现

参数设置

cpp 复制代码
import cv2

# 读取图像
img = cv2.imread('your_image.jpg')

# 保存为不同格式
cv2.imwrite('output_image.jpg', img, [int(cv2.IMWRITE_JPEG_QUALITY), 90])  # JPEG,质量90
cv2.imwrite('output_image.png', img, [int(cv2.IMWRITE_PNG_COMPRESSION), 5])  # PNG,压缩级别5

print("图像已保存。")
cpp 复制代码
import cv2 

img = cv2.imread('your_image.jpg')

# JPEG 质量90
cv2.imwrite('output_image.jpg',img,[int(cv2.IMWRITE_JPEG_QUALITY),90])
cv2.imwrite('output_image.png',img,[int(cv2.IMWRITE_PNG_COMPRESSION),5])

参数调整总结

  • **JPEG质量参数:**数值越高,图像质量越好,相应的文件体积越大
  • **PNG压缩级别:**数值越高,压缩率越高,文件体积也就越小

计算机图形学知识补充

图像编码与压缩

  • **无损压缩:**例如PNG,图像的质量不受损失,但是文件的体积较大
  • **有损压缩:**例如JPEG,会舍弃部分的像素来达到压缩的目的,文件体积会更小

保存图像函数实现分析

图像保存会调用编码库,会将NumPy数组编码为指定格式的图像文件,其中编码参数params传递给编码器,从而控制压缩质量和压缩级别

调整图像大小

基本操作

  • cv2.resize(src , dsize , fx=0 , fy=0 , interolation = cv2.INTER_LINEAR): 按照指定的尺寸或者缩放比例去调整图像大小
    • 参数
      • src:输出图像
      • desize:输出图像的尺寸(宽、高)
      • fx,fy:水平和垂直方向的缩放因子
      • interpolation:插值方法
    • 插值方法
      • cv2.INTER_NEAREST: 最近邻插值,速度快,质量低
      • cv2.INTER_LINEAR: 双线性插值,默认值,适用于放大
      • cv2.INTER_AREA: 区域插值,适用于缩小
      • cv2.INTER_CUBIC: 三次插值,质量较高,速度较慢

代码实现

cpp 复制代码
#调整尺寸
import cv2 

img = cv2.imread('your_image.jpg')

#按比例将其缩放成原来的一半
resized_img = cv2.resize(img,None,fx=0.5,fy=0.5,interpolation=cv2.INTER_AREA)

#保存查看
cv2.imwrite('resized_image.jpg',resized_img)

参数调整测试

cpp 复制代码
import cv2

# 读取图像
img = cv2.imread('your_image.jpg')

# 指定输出尺寸
resized_img_fixed = cv2.resize(img, (800, 600), interpolation=cv2.INTER_LINEAR)

# 使用缩放因子
resized_img_scale = cv2.resize(img, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_LINEAR)

# 使用不同的插值方法
resized_img_nearest = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_NEAREST)
resized_img_cubic = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC)

# 保存结果
cv2.imwrite('resized_fixed.jpg', resized_img_fixed)
cv2.imwrite('resized_scale.jpg', resized_img_scale)
cv2.imwrite('resized_nearest.jpg', resized_img_nearest)
cv2.imwrite('resized_cubic.jpg', resized_img_cubic)
  • 通过改变输出尺寸与缩放因子,可以调整图像的大小
  • 不同的插值方法会影响图像的质量,最近邻插值可能会出现像素化,三次插值则会更加的平滑

计算机图像学相应知识

图像缩放与插值

  • 图像缩放,主要就是改变图像分辨率,需要重新计算其像素值
  • 插值算法:用于估计新的像素值,常见的右最近邻、双线性、双三次插值等
    • 处理图像的时候,插值算法主要用于在图像缩放和旋转的时候生成新像素
    • 也就是说当要放大或者缩小图像的时候,原图中的像素不够使用了,插值算法就是用来填补这些空白区域的,目的就是为了让变换后的新图像看起来更加的平滑自然

插值方法原理理解

  • 最近邻插法: 选择最接近的像素值,简单但是可能会出现锯齿或者马赛克的效果
    • 观察哪个已有像素距离新位置最近,然后直接将这个最近的像素颜色搬运过来
    • 也就类似于在放大图片的时候,直接把原来的像素点扩大复制出来,这样省时省力,但是结果可能会出现锯齿现象,图像看起来也就不平滑
    • 具体理解,类似于网格纸上的像素画,该算法就是暴力将每个格子放大几倍,但是格子的颜色不变,这样放大后的图像在视觉上一定是存在锯齿形状
  • 双线性插值: 根据周围四个像素的加权平均计算,效果比较好
    • 考虑周围4个像素,并根据这些像素做一个加权平均生成一个新的像素,也就是根据周围的颜色混合出一个中间值,所以图像会比最近邻插值平滑的多
    • 根据周围的四个颜色计算出一个过度色,从而更加自然
  • 双三次插值: 考虑周围16个像素,计算更加复杂一些,效果更加平滑
    • 考虑16个相邻的像素,然后利用数学公式生成新的像素,这样就会让边缘和细节更加清晰
  • 超分辨率插值
    • 该种方法不是简单的利用周围元素生成新的像素,而是利用机器学习来理解图像的内容,甚至预测出新的细节,所以该种方法可以恢复一些模糊的部分

调整图像背后实现理解

  • 重采样:计算机通过对目标图像每个像素在源图像的对应位置,使用插值方法计算新的像素值
  • 插值计算:根据插值算法,对源图像的像素值进行加权平均,最终得到目标像素值

转换色彩空间

基本操作

  • cv2.cvtColor(src , code): 转换图像颜色空间,主要用于不同颜色空间之间的转换(BGR转换到灰度)
    • src :输入的图像
    • code:颜色空间转换代码
      • cv2.COLOR_BGR2GRAY: BGR 转 灰度
      • cv2.COLOR_BGR2HSV: BGR 转 HSV
      • cv2.COLOR_BGR2RGB: BGR 转 RGB
  • OpenCV默认的颜色空间是BGR

代码实践

cpp 复制代码
#颜色空间转换
import cv2

img = cv2.imread('your_image.jpg')

#转换为灰度图像
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

#保存灰度图像
cv2.imwrite('gray_image.jpg',gray_img)

实现原理理解

  • 该函数会使用预定义的转换公式,将像素值从一种颜色空间映射到另一种颜色空间
  • 颜色空间的转换会涉及到对图像的每一个像素和通道进行计算

计算机图形学相应知识补充

颜色空间

  • BGR/RGB:基于三原色的颜色模型,一般用于显示设备
  • HSV(色调、饱和度、明度):接近于人类感知,主要用于处理颜色分析和处理

颜色空间转换

  • **线性转换:**部分颜色空间是可以直接通过线性变换转换
  • 非线性转换:RGB转换为HSV,就需要使用到非线性公式

图像裁剪

基本说明

  • 图像在OpenCV中是以NumPy数组形式表示,所以图像裁剪可以使用数组切片的方式实现
  • 数组切片:img[y1:y2 , x1:x2] ,先行后列
    • y1:y2:行索引范围(高度)
    • x1:x2:列索引范围(宽度)

代码实践

cpp 复制代码
import cv2

img = cv2.imread('your_image.jpg')

#裁剪图像,获取[100,100]到[400,400]
cropped_img = img[100:400,100:400]

#保存图像
cv2.imwrite('cropped_image.jpg',cropped_img)

函数实现

  • 图像在内存中是以二维或者三维数值表示的,裁剪操作实际上就是对数组进行切片
  • 裁剪得到的图像与原图像共享内存,修改裁剪后的图像会影响原图像

计算机原理知识补充

ROI(感兴趣区域

  • 图像中需要处理或者分析的特定区域,主要用于降低计算量,聚焦于关键部分
    • ROI是图像中的一块区域,当对这个区域的内容感兴趣的时候,并且需要在这个部分进行处理、分析或者提取信息
    • 例如在对一张风景照进行处理,只是对该图片上的一朵花感兴趣,那么只需要提取这朵花的ROI区域,那么接下来的操作就可以对这朵花进行操作,例如放大、修改其形状等
  • 实现流程
    • 确定ROI的位置,即通过矩形划出感兴趣的部分,然后提取ROI,作为一个独立的小图像
    • 处理ROI,针对于该块区域进行处理,最后将ROI还原到原图即可
  • 裁剪,即是选取图像中感兴趣的部分,类似于用剪刀将照片上剪下一块

ROI实验

cpp 复制代码
import cv2

# 读取图像
img = cv2.imread('your_image.jpg')

# 定义 ROI 区域(假设已知需要裁剪的坐标)
x, y, w, h = 100, 100, 200, 200  # 左上角坐标 (x, y),宽度 w,高度 h

# 裁剪 ROI
roi = img[y:y+h, x:x+w]

# 对 ROI 进行处理,例如转换为灰度
roi_gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)

# 将处理后的 ROI 放回原图(需要匹配通道数)
roi_color = cv2.cvtColor(roi_gray, cv2.COLOR_GRAY2BGR)
img[y:y+h, x:x+w] = roi_color

# 保存结果
cv2.imwrite('processed_image.jpg', img)

绘制形状和添加文字

基本方法

  • cv2.line(img , pt1 , pt2 , color , thickness , lineType):绘制直线
    • pt1 , pt2 :起点和终点坐标
    • color:线条颜色(B G R)
    • thickness:线条厚度
    • lineType
      • cv2.LINE_8: 8-connected line(默认)
      • cv2.LINE_AA: 抗锯齿线条,效果更平滑
      • cv2.LINE_4: 4-connected line
  • cv2.rectangle(img , pt1 , pt2 , color-BGR , thickness,lineType,shift ):绘制矩形
    • img:目标图像
    • pt1:矩形左上角顶点(x,y)
    • pt2:矩形的右下顶点
    • color:矩形边框颜色
    • thickness(可选):边框的厚度,如果将其设置为负数或者cv2.FILLED矩形将被填充
    • lineType(可选):边框线条类型
    • shift(可选):坐标的小数位表示
  • cv2.circle(img , center , radius , color , thickness=None , lineType=None , shift=None):绘制圆形
    • img:目标图像
    • center:圆心位置
    • radius:圆的半径
    • color:圆的颜色
    • thickness(可选):元边框的厚度
  • cv2.putText(img , text , org , fontFace , fontScale , color , thickness=None,lineType=None,bottomLeftOrigin=None):在图形上添加文字
    • img:目标图像
    • text:要绘制的文本字符串
    • org :文本左下角的起始位置,格式为 (x, y)
    • fontFace :字体类型。常用的字体类型:
      • cv2.FONT_HERSHEY_SIMPLEX: 常用字体,正常大小
      • cv2.FONT_HERSHEY_PLAIN: 非常小的字体
      • cv2.FONT_HERSHEY_DUPLEX: 比较粗的字体
      • cv2.FONT_HERSHEY_COMPLEX: 比较复杂的字体
      • cv2.FONT_HERSHEY_TRIPLEX: 更复杂的字体
      • cv2.FONT_HERSHEY_COMPLEX_SMALL: 小字体
      • cv2.FONT_HERSHEY_SCRIPT_SIMPLEX: 类似手写字体
      • cv2.FONT_HERSHEY_SCRIPT_COMPLEX: 更复杂的手写字体
    • fontScale:字体的缩放比例(大小)
    • color :文本颜色,格式为 (B, G, R)
    • thickness (可选):文本线条的粗细,默认为 1
    • lineType (可选):线条类型,通常是 cv2.LINE_AA 抗锯齿
    • bottomLeftOrigin (可选):如果为 True,则文本原点为左下角,默认是 False,即左上角为原点

代码实践

cpp 复制代码
#绘制文字与添加形状
import cv2 
import numpy as np

#创建纯黑色背景
img = np.zeros((512,512,3),np.uint8)

#蓝色直线,左上角到右下角
cv2.line(img,(0,0),(511,511),(255,0,0),5)

#绿色矩形,左上角到右下角
cv2.rectangle(img,(100,100),(400,400),(0,255,0),3)

#红色圆形,中心坐标和半径
cv2.circle(img,(256,256),50,(0,0,255),-1) #-1是填充的意思

#添加文字
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img,'openCv_stu',(10,500),font,2,(255,255,255),2,cv2.LINE_AA)

#保存结果
cv2.imwrite('shapes_text.jpg',img)

参数调整分析

cpp 复制代码
import cv2
import numpy as np

# 创建黑色图像
img = np.zeros((512, 512, 3), np.uint8)

# 绘制不同厚度和颜色的线条
cv2.line(img, (50, 50), (462, 50), (255, 0, 0), 1)
cv2.line(img, (50, 100), (462, 100), (0, 255, 0), 3)
cv2.line(img, (50, 150), (462, 150), (0, 0, 255), 5)

# 绘制填充和非填充的矩形
cv2.rectangle(img, (50, 200), (200, 350), (255, 255, 0), 3)
cv2.rectangle(img, (250, 200), (450, 350), (255, 0, 255), -1)

# 绘制不同半径的圆形
cv2.circle(img, (256, 400), 50, (0, 255, 255), 2)
cv2.circle(img, (256, 400), 30, (255, 255, 255), -1)

# 添加不同字体和大小的文字
fonts = [cv2.FONT_HERSHEY_SIMPLEX, cv2.FONT_HERSHEY_COMPLEX]
cv2.putText(img, 'OpenCV', (10, 450), fonts[0], 1, (255, 255, 255), 2)
cv2.putText(img, 'Graphics', (10, 500), fonts[1], 2, (255, 255, 255), 3)

# 保存结果
cv2.imwrite('drawings.jpg', img)

计算机图形学补充

光栅化与绘制

  • 光栅化就是将几何图形转换为像素阵列
  • 光栅图形
    • 由像素组成的图像,类似于一个由多个小方格组成的画,每个方格都有颜色
  • 抗锯齿即是通过灰度处理平滑边缘,减少锯齿效果

矢量图形

  • 使用数学描述图形,放大不会模糊
  • 矢量图形是可以实现无损缩放、光栅图形由像素组成,缩放会失真

图像算术运算

基本操作

  • cv2.add():图像相加
  • cv2.addWeighted(src1 , alpha , scr2 , beta , gamma):图像融合
    • src1 , src2 :输入图像
    • alpha , beta:图像的权重
    • gamma:加到结果上的标量值

代码实践

cpp 复制代码
#图像运算
import cv2 

#读取两个相同尺寸的图片
img1 = cv2.imread('image1.jpg')
img2 = cv2.imread('image2.jpg')

#简单相加
added_img = cv2.add(img1,img2)

#两张图像融合
blended_img = cv2.addWeighted(img1,0.7,img2,0.3,0)

#保存结果
cv2.imwrite('added_imge.jpg',added_img)
cv2.imwrite('boended_image.jpg',blended_img)

参数调整测试

cpp 复制代码
import cv2

# 读取图像
img1 = cv2.imread('image1.jpg')
img2 = cv2.imread('image2.jpg')

# 确保图像尺寸相同
img2 = cv2.resize(img2, img1.shape[1::-1])

# 不同权重的加权融合
blended_img1 = cv2.addWeighted(img1, 0.2, img2, 0.8, 0)
blended_img2 = cv2.addWeighted(img1, 0.5, img2, 0.5, 0)
blended_img3 = cv2.addWeighted(img1, 0.8, img2, 0.2, 0)

# 保存结果
cv2.imwrite('blended_20_80.jpg', blended_img1)
cv2.imwrite('blended_50_50.jpg', blended_img2)
cv2.imwrite('blended_80_20.jpg', blended_img3)

计算机图形学知识补充

图像融合

  • 加权平均:对两张图像的像素值按照权重求和,实现融合效果
  • Alpha通道:用于表示图像的透明度,在图像叠加的时候起作用

像素级运算

  • 逐像素计算: 对图像的每个像素进行算术运算,生成新的图像
    • 对图像中的每个元素进行计算,就像个每个像素加上一样的亮度
  • 图像融合
    • 将两个图像按照一定比例进行叠加,从而产生融合效果,类似于PS中的正片叠底等效果

图像阈值处理

基本操作

  • cv2.threshold(src , thresh , maxval , type):主要负责对图像的阈值进行处理,阈值就是用来将灰度图像二值化,根据阈值将像素进行分类
    • src:输出灰度图像
    • thresh:阈值
    • maxval:当满足条件的时候,赋予的像素值
    • type:阈值类型
      • cv2.THRESH_BINARY: 大于阈值的像素赋值为 maxval,否则为 0
      • cv2.THRESH_BINARY_INV: 反转的二值化
      • cv2.THRESH_TRUNC: 大于阈值的像素赋值为阈值
      • cv2.THRESH_TOZERO: 大于阈值的保留,其他设为 0
  • 注意其返回值有两个,以代码事例来说,ret是阈值,thresh_img是处理后的图像

代码实践

cpp 复制代码
import cv2 

#读取灰度图像
gray_img = cv2.imread('gray_image.jpg',0)

#应用全局阈值
ret,thresh_img = cv2.threshold(gray_img,127,255,cv2.THRESH_BINARY)

#保存处理结果
cv2.imwrite('threshold_image.jpg',thresh_img)

参数调整测试

cpp 复制代码
import cv2

# 读取灰度图像
gray_img = cv2.imread('gray_image.jpg', 0)

# 应用不同阈值和类型
ret, thresh_binary = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY)
ret, thresh_binary_inv = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh_trunc = cv2.threshold(gray_img, 127, 255, cv2.THRESH_TRUNC)
ret, thresh_tozero = cv2.threshold(gray_img, 127, 255, cv2.THRESH_TOZERO)

# 保存结果
cv2.imwrite('thresh_binary.jpg', thresh_binary)
cv2.imwrite('thresh_binary_inv.jpg', thresh_binary_inv)
cv2.imwrite('thresh_trunc.jpg', thresh_trunc)
cv2.imwrite('thresh_tozero.jpg', thresh_tozero)

计算机图形学概念理解

阈值处理

  • 阈值处理理解
    • 类似于一张黑白照片,然后手动管设定一个亮度数值,照片上比这个亮度更亮的部分都变成的了白色,低于这个亮度的部分都变成了黑色,该操作就是阈值处理
    • 阈值处理就是设定了一个门槛值,将图像的像素分成的两类,一类就是高于这个门槛的像素,另一个就是低于这个门槛的像素,一般用于区分图像前景和后景
  • 图像分割: 根据像素值,将图像分为前景和背景
    • 将自己想要的图像分割出来,但是这个区分标准是基于像素的亮度
  • 直方图分析:通过图像的灰度直方图,选择合适的阈值
    • 首先直方图就是一个统计表,该直方图中显式的告诉照片中有多少亮的像素和多少暗的像素,这样就可以合理的找出自己想要设定的阈值
    • 例如一张黑白图片,上面主要有亮的和暗的物体,直方图中就统计了这张照片亮和暗的像素有多少,然后设计了一个统计表,然后就可以利用直方图将明暗区域分开

自动阈值算法

  • 大津算法:自动计算最佳阈值,最大化类间方差
    • 大津算法就是在照片中找到一个最佳的分界线,让前景物体和背景区分最明显
    • 也就是自动帮忙找到最佳阈值,从而找到最佳分割亮度值

图像平滑(模糊)

基本操作

  • **主要功能:**图像平滑主要就是用来降低噪声,改善图像质量
  • **滤波核大小:**核越大,模糊的程度就越高
  • **高斯滤波:**比均值更加平滑,保留边缘能力更强
  • cv2.blur(src , ksize):均值滤波
    • ksize:滤波核大小
  • cv2.GaussianBlur(src , kszie , sigmaX):高斯滤波
    • sigmaX:高斯核在X方向的标准差
  • cv2.medianBlur(src , ksize)
    • ksize:滤波核大小,必须是奇数

代码实践

cpp 复制代码
#图像平滑
import cv2 

img = cv2.imread('your_image.jpg')

#均值滤波
blur_img = cv2.blur(img,(10,10))

#高斯滤波
gaussian_img = cv2.GaussianBlur(img,(5,5),0)

cv2.imwrite('blur_image.jpg',blur_img)
cv2.imwrite('gaussian_image.jpg',gaussian_img)

参数调整变化分析

计算机图形学知识补充

滤波器

  • 滤波器 ,类似于PS中的模版或者工具,可以达到模糊、锐化等效果,就像在照片上盖了一层透明的薄膜一样
    • 不同滤波器的理解:卷积就像手中拿到的放大镜,观察图像中的每一个部分,然后使用滤波器,类似的滤波器不同的类型可以让图像达到不同的效果
  • **空间域滤波:**直接在图像像素空间上进行操作
  • 卷积操作: 滤波器与图像进行卷积,从而得到平滑效果
    • 将滤波器在图像上滑动,对对应的像素进行运算,这就像用滚筒在墙上刷漆一样
    • 本身是一种数学运算,通过将滤波器核与图像进行点积,得到滤波后的结果

高斯滤波器

  • 其权重按照高斯分布,中心权重大,边缘权重小
  • 主要用于平滑噪声以及保留边缘信息

不同滤波器实践验证

  • 均值滤波对随机噪声有一定抑制作用,但会模糊边缘
  • 高斯滤波保留边缘的能力较好,适合去除高斯噪声
  • 中值滤波对椒盐噪声有很好的去除效果
cpp 复制代码
import cv2

# 读取图像
img = cv2.imread('your_image.jpg')

# 均值滤波
mean_blur = cv2.blur(img, (5, 5))

# 高斯滤波
gaussian_blur = cv2.GaussianBlur(img, (5, 5), 1)

# 中值滤波
median_blur = cv2.medianBlur(img, 5)

# 保存结果
cv2.imwrite('mean_blur.jpg', mean_blur)
cv2.imwrite('gaussian_blur.jpg', gaussian_blur)
cv2.imwrite('median_blur.jpg', median_blur)

边缘处理

基本用法

  • 边缘检测主要用于提取图像中的边缘信息
  • cv2.Canny( image , threshold1 , threshold2 , aertureSize=3 , L2gradient=False):边缘检测算法
    • image( 输入图像)
      • 必须是单通道的灰度图像,如果输入的是彩色图像,需要先将其转为灰度图像,然后进行边缘检测
    • threshold1 , threshold2 : 低阈值与高阈值
      • 低阈值,表示任何小于该值的像素梯度将会被认为不是边缘,低阈值直接影响检测出边缘的数量和强度
      • 高阈值,任何大于该值的像素梯度都会被认为是边缘,高阈值会直接的影响边缘的强度和检测的灵敏度
    • aertureSize: Sobel算子的大小,默认是3
      • Sobel算子就是用于计算图像梯度的卷积核尺寸,该算子是一种用于检测边缘的算子
      • apertureSize的数值必须是奇数,卷积和越大,计算出来梯度就越精细,但是可能也会导致边缘模糊
    • **L2gradient:**是否使用更加精确的L2范数进行梯度的运算

代码实践

参数调整

结论: 改变阈值可以控制检测到的边缘数量;增大aertureSize,可以检测到更粗的边缘

cpp 复制代码
import cv2 

gray_img = cv2.imread('gray_image.jpg',0)

#不同阈值边缘检测
edges_50_150 = cv2.Canny(gray_img, 50, 150)
edges_100_200 = cv2.Canny(gray_img, 100, 200)
edges_150_250 = cv2.Canny(gray_img, 150, 250)

# 使用不同的 apertureSize
edges_aperture_5 = cv2.Canny(gray_img, 100, 200, apertureSize=5)

# 保存结果
cv2.imwrite('edges_50_150.jpg', edges_50_150)
cv2.imwrite('edges_100_200.jpg', edges_100_200)
cv2.imwrite('edges_150_250.jpg', edges_150_250)
cv2.imwrite('edges_aperture_5.jpg', edges_aperture_5)

计算机图形学知识补充

边缘检测算法

  • Canny边缘检测:多级边缘检测算法,
  • Sobel算子:用于计算图形的梯度

梯度

  • 梯度就是图像中像素值变化的程度,就像山坡的坡度,坡度越大变化也就越明显
  • 图像处理中的梯度,表示的是在空间位置上的变化率,是向量,包含幅值和方向
  • 课本概念理解
    • 梯度是图像中亮度(灰度值)变化的方向和强度,对于每个像素,梯度是一个向量,其指的是像素值变化最快的方向
    • Gx:图像在水平方向的变化
    • Gy:图像上垂直方向上变化
相关推荐
viperrrrrrrrrr73 小时前
大数据学习(105)-Hbase
大数据·学习·hbase
行思理5 小时前
go语言应该如何学习
开发语言·学习·golang
oceanweave6 小时前
【k8s学习之CSI】理解 LVM 存储概念和相关操作
学习·容器·kubernetes
吴梓穆8 小时前
UE5学习笔记 FPS游戏制作43 UI材质
笔记·学习·ue5
学会870上岸华师8 小时前
c语言学习16——内存函数
c语言·开发语言·学习
XYN618 小时前
【嵌入式面试】
笔记·python·单片机·嵌入式硬件·学习
啊哈哈哈哈哈啊哈哈8 小时前
R3打卡——tensorflow实现RNN心脏病预测
人工智能·深度学习·学习
KangkangLoveNLP9 小时前
深度探索:策略学习与神经网络在强化学习中的应用
人工智能·深度学习·神经网络·学习·机器学习·自然语言处理
穷儒公羊10 小时前
第一部分——Docker篇 第六章 容器监控
运维·后端·学习·docker·云原生·容器
CAE虚拟与现实10 小时前
记录一下学习docker的命令(不断补充中)
学习·docker·容器·容器化·docker部署·docker命令