opencv之图像亮度变换和形态学变换(八)

opencv之图像亮度变换和形态学变换(八)


一、图像亮度变换

1.1 亮度变换

在讲解亮度时,需要和对比度一起来进行解释。

对比度调整:图像暗处像素强度变低,图像亮处像素强度变高,从而拉大中间某个区域范围的显示精度。

亮度调整:图像像素强度整体变高或者变低。

在这里插入图片描述
上图中,(a)把亮度调高,就是图片中的所有像素值加上了一个固定值;(b)把亮度调低,就是图片中的所有像素值减去了一个固定值;©增大像素对比度(白的地方更白,黑的地方更黑);(d)减小像素对比度(整幅图都趋于一个颜色);

OpenCV调整图像对比度和亮度时,公式为: g ( i , j ) = α f ( i , j ) + β g(i,j)=\alpha f(i,j)+\beta g(i,j)=αf(i,j)+β。但是不能浅显的讲 α \alpha α是控制对比度, β \beta β是控制亮度的。

对比度:需要通过 α 、 β \alpha、\beta αβ一起控制。

亮度:通过 β \beta β控制。

1.2 线性变换

使用 cv2.addWeighted() 函数,可以对图像的像素值进行加权平均,进而改变图像的整体亮度。亮度增益可以通过向每个像素值添加一个正值来实现。

cv2.addWeighted(src1, alpha, src2, beta, gamma)

  • src1:第一张输入图像,它将被赋予权重 alpha

  • alpha:第一个输入图像的权重。

  • src2:第二张输入图像,它将被赋予权重 beta

  • beta:第二个输入图像的权重。

  • gamma:一个标量,将被添加到权重求和的结果上,可用于调整总体亮度。

    计算公式为: dst = src1 * alpha + src2 * beta + gamma

1.3 直接像素值修改

如果只需要增加或减少固定的亮度值,可以直接遍历图像像素并对每个像素值进行加减操作。

使用的API:

numpy.clip(a, a_min, a_max)

用于对数组中的元素进行限定,将超出指定范围的元素值截断至指定的最小值和最大值之间

  • a:输入数组。

  • a_min:指定的最小值,数组中所有小于 a_min 的元素将被替换为 a_min

  • a_max:指定的最大值,数组中所有大于 a_max 的元素将被替换为 a_max

案例

案例一

import numpy as np
import cv2 as cv

img = cv.imread("images/1.jpg")
# 使用cv2.addWeihted(src1, alpha, src2, beta, gamma)实现线性变换
"""
np.zeros_like(img) 生成与img相同形状的零矩阵
np.ones_like(img) 生成与img相同形状的1矩阵
np.full_like(img, n) 生成与img相同形状的n矩阵
"""
dst = cv.addWeighted(img, 1, np.zeros_like(img), 0, 50)

cv.imshow("dst", dst)
cv.imshow("img", img)
cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

案例二

import cv2 as cv
import numpy as np

window_name = 'Trackbar'
cv.namedWindow(window_name)

# 写一个改变图像亮度的方法
def change(p):
    img = cv.imread('images/1.jpg')
    if img is None:
        print("图像加载失败,请检查路径!")
        return
    # 把滑条范围映射到-255~255
    p = int(p)  # 确保 p 是整数
    p = p / 255 * (255 - (-255)) - 255
    # 亮度变换
    dst = np.uint8(img + p)
    dst = np.clip(dst, 0, 255)
    cv.imshow(window_name, dst)

# 创建滑条
cv.createTrackbar('p', 'Trackbar', 0, 255, change)

# 初始化显示
change(0)  # 初始化时调用一次,确保图像显示

cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

二、形态学变换

形态学变换(Morphological Transformations)是一种基于形状的简单变换,它的处理对象通常是二值化图像。形态学变换有两个输入,一个输出:输入为原图像、核(结构化元素),输出为形态学变换后的图像。其基本操作有腐蚀和膨胀,这两种操作是相反的,即较亮的像素会被腐蚀和膨胀。下面我们来说一下核、腐蚀与膨胀的概念。

2.1 核

自适应二值化中,我们已经接触过核了,还记得吗?就是那个在原图中不断滑动计算的3*3的小区域,那其实就是一个3*3的核。

核(kernel)其实就是一个小区域,通常为3*3、5*5、7*7大小,有着其自己的结构,比如矩形结构、椭圆结构、十字形结构,如下图所示。通过不同的结构可以对不同特征的图像进行形态学操作的处理。
在这里插入图片描述

2.2 腐蚀(Erosion)

  • 作用:收缩白色区域(前景),消除小噪点、细线
  • 原理:结构元素覆盖区域内有黑即黑(取最小值)
  • 效果:目标"变瘦",边缘平滑

2.3 膨胀(Dilation)

  • 作用:扩展白色区域,填补空洞、断裂
  • 原理:结构元素覆盖区域内有白即白(取最大值)
  • 效果:目标"变胖",轮廓连通

2.4 开运算(Opening)

  • 操作:先腐蚀后膨胀
  • 作用:消除孤立噪点、分离粘连物体
  • 特点:保留原主体,去除小干扰

2.5 闭运算(Closing)

  • 操作:先膨胀后腐蚀
  • 作用:填充内部孔洞、闭合缝隙
  • 特点:平滑轮廓,保持主体完整性

2.6 礼帽运算(Top Hat)

  • 公式:原图 - 开运算结果
  • 作用:提取比背景亮的细节(如微小亮斑)
  • 应用:背景均匀时的前景增强

2.7 黑帽运算(Black Hat)

  • 公式:闭运算结果 - 原图
  • 作用:提取比背景暗的细节(如暗色缺陷)
  • 应用:检测深色区域或空洞

2.8 形态学梯度(Morphological Gradient)

  • 公式:膨胀图 - 腐蚀图
  • 作用:突出边缘轮廓
  • 效果:类似边缘检测,但更平滑

核心总结

操作关键作用典型应用场景
腐蚀消除噪点、细化物体去除胡椒噪声
膨胀连接断裂、填充孔洞文字修复
开运算去噪+保形分离粘连细胞
闭运算补洞+平滑填充指纹断裂
礼帽提取亮细节显微图像亮斑提取
黑帽提取暗细节工业缺陷检测
形态学梯度边缘增强目标轮廓提取

:所有操作均依赖**结构元素(核)**的形状和大小选择!

案例

案例一:腐蚀和膨胀

import cv2 as cv
import numpy as np

long = cv.imread("images/long.png")
# 定义一个5×5的卷积核
kernel = np.ones((5,5),np.uint8)
# 腐蚀操作cv.erode(src, kernel, dst, anchor, iterations, borderType, borderValue)
# iterations表示迭代次数
dst_erode = cv.erode(long,kernel,iterations=1)

# 膨胀操作cv.dilate(src, kernel, dst, anchor, iterations, borderType, borderValue)
dst_dilate = cv.dilate(long,kernel,iterations=5)

cv.imshow("long",long)
cv.imshow("dst_erode",dst_erode)
cv.imshow("dst_dilate",dst_dilate)
cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

案例二

import cv2 as cv
import numpy as np

car = cv.imread("images/car4.png")
car = cv.resize(car,(640,480))
# 定义一个5×5的卷积核
kernel = np.ones((5,5),np.uint8)
# 开运算 cv.morphologyEx(src,op,kernel) # 先腐蚀再膨胀
open = cv.morphologyEx(car,cv.MORPH_OPEN,kernel)
# 闭运算 cv.morphologyEx(src,op,kernel) # 先膨胀再腐蚀
close = cv.morphologyEx(car,cv.MORPH_CLOSE,kernel)

# 显示图像
cv.imshow("car",car)
cv.imshow("open",open)
cv.imshow("close",close)
cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

案例三

import cv2 as cv
import numpy as np

car = cv.imread("images/car4.png")
car = cv.resize(car,(640,480))
# 定义一个5×5的卷积核
kernel = np.ones((5,5),np.uint8)
# 礼帽运算cv.morphologyEx(src,op,kernel) 原图减"开运算"
dst_top = cv.morphologyEx(car,cv.MORPH_TOPHAT,kernel)

# 黑帽运算cv.morphologyEx(src,op,kernel) "闭运算"的结果图与原图像之差
dst_black = cv.morphologyEx(car,cv.MORPH_BLACKHAT,kernel)

cv.imshow("car",car)
cv.imshow("dst_top",dst_top)
cv.imshow("dst_black",dst_black)
cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

案例四

import cv2 as cv
import numpy as np

car = cv.imread("images/car4.png")
car = cv.resize(car,(640,480))
# 定义一个5×5的卷积核
kernel = np.ones((5,5),np.uint8)
# 形态学梯度 cv2.morphologyEx(src,op,kernel) 像素点在膨胀后的图像值与其在腐蚀后的图像值之差
gradient = cv.morphologyEx(car,cv.MORPH_GRADIENT,kernel)
cv.imshow("gradient",gradient)
cv.imshow("car",car)
cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值