空间域滤波是直接对图像的像素进行处理,根据滤波器的作用不同,又可分为线性滤波和非线性滤波。
频率域滤波是先将图像从空间域转换到频率域,在频率域中对图像的频率成分进行处理,然后再将处理后的图像转换回空间域。常用的频率域滤波方法包括低通滤波、高通滤波、带通滤波和带阻滤波等。
空间域增强是直接对图像的像素灰度值进行操作,主要包括灰度变换和空间滤波。
频率域增强是将图像从空间域转换到频率域,在频率域中对图像的频率成分进行处理,然后再转换回空间域。
彩色图像增强不仅要考虑图像的亮度信息,还要考虑颜色信息,常见的方法有真彩色增强和假彩色增强。
随着深度学习技术的发展,基于深度学习的图像增强方法取得了显著的成果。
逆滤波复原:
通过傅里叶变换将图像转换到频域,利用公式$F^\prime(u,v) = G(u,v)/H(u,v)$(其中$G(u,v)$为退化图像频域表示,$H(u,v)$为退化函数)直接求解原始图像估计值。但该方法在$H(u,v)$接近零时可能失效,且对噪声敏感,需在分母中加入常数或限制滤波频率以改进。
维纳滤波复原:
基于最小均方误差准则,利用噪声和图像的统计信息恢复图像。其传递函数为$H(u,v)=\frac{H^*(u,v)P_f(u,v)}{|H(u,v)|^2P_f(u,v)+P_n(u,v)}$,其中$P_f(u,v)$和$P_n(u,v)$分别为图像和噪声的功率谱。该方法可自动抑制噪声放大,但需较多先验知识。
有约束最小二乘复原:
在约束条件下寻找使准则函数最小的复原图像,通常采用平滑约束(如使原始图像的二阶导数平方和最小)。通过拉格朗日乘数法求解,适用于噪声统计特性未知的情况。
deconvblind函数(如MATLAB中)进行复原,适用于无法准确获取退化模型参数的场景。空间滤波复原:
针对噪声存在的情况,采用均值滤波器(如算术均值、几何均值、谐波均值、逆谐波均值滤波器)或自适应滤波器(如自适应中值滤波器)进行去噪和复原。
频率域滤波复原:
通过傅里叶变换将图像转换到频域,利用带阻滤波器、带通滤波器或陷波滤波器消除噪声或特定频率分量。例如,使用n阶巴特沃思带阻滤波器或高斯带阻滤波器进行周期噪声的削减。
物理模型复原:
基于光学和成像系统的物理原理(如反射、折射、衍射),模拟图像形成过程和退化现象,设计反卷积算法以重建清晰图像。例如,通过模拟运动模糊来设计反卷积算法。
统计模型复原:
基于图像数据的概率分布和统计特性(如噪声模型、图像纹理模型、统计相关性),从数据层面理解和解释图像特性。例如,利用Wiener滤波进行基于噪声统计特性的去噪。
原理:根据像素灰度值设定阈值,将图像分为前景和背景。
适用场景:目标与背景灰度差异明显的图像。
全局阈值法
自适应阈值法
原理:检测图像中灰度或颜色突变的边缘,连接边缘形成区域。
适用场景:目标边缘清晰、对比度高的图像。
边缘检测算子
边缘连接
原理:根据像素相似性将图像划分为区域。
适用场景:目标内部颜色或纹理均匀的图像。
区域生长
区域分裂与合并
分水岭算法
原理:将像素聚类为具有相似特征的组。
适用场景:无监督学习场景。
K-means聚类
Mean Shift聚类
原理:将图像建模为图,通过优化分割准则划分节点。
适用场景:需要全局优化的复杂场景。
Graph Cut
Normalized Cut(Ncut)
GrabCut
原理:利用卷积神经网络(CNN)自动学习特征,实现端到端分割。
适用场景:复杂场景、大规模数据集。
全卷积网络(FCN)
U-Net
Mask R-CNN
DeepLab系列
Transformer-based方法
基于活动轮廓模型(Snake)
超像素分割
弱监督/无监督分割
图像分割方法的选择需综合考虑数据特性、计算资源和任务需求。传统方法(如阈值、边缘检测)计算简单,但泛化能力有限;深度学习方法(如FCN、U-Net)性能强大,但依赖大量标注数据。未来趋势包括:
cv2.imread() 用于读取图片文件,imread() 函数有两个参数,第一个参数是图片路径,第二个参数表示读取图片的形式,有三种
cv2.IMREAD_COLOR:加载彩色图片,这个是默认参数,可以直接写 1
cv2.IMREAD_GRAYSCALE:以灰度模式加载图片,可以直接写 0
cv2.IMREAD_UNCHANGED:包括 alpha,可以直接写 -1
cv2.imwrite() 用于保存一个图像。第一个参数是要保存的文件名,第二个参数是要保存的图像。
第一个参数是图片
第二个参数是要缩放的大小,如(256, 256)图像放缩到256
是一个用于等待用户按键输入的函数。默认参数 0 表示无限期等待,直到用户按下任意键为止
cv2.waitKey(1): 等待 1 毫秒,如果在这段时间内没有按键按下,则继续执行后续代码。这通常用于视频处理或实时显示图像时,以控制帧率
关闭所有OpenCV窗口
gray_image = cv2.cvtColor(image_path, cv2.COLOR_BGR2GRAY)
第一个参数是源图像
第二个参数是转换代码:
cv2.COLOR_BGR2GRAY:BGR 到灰度
cv2.COLOR_GRAY2BGR:灰度到 BGR
cv2.COLOR_BGR2HSV:BGR 到 HSV
cv2.COLOR_HSV2BGR:HSV 到 BGR
HSV 表示色调(Hue)、饱和度(Saturation)和明度(Value)
两个参数:一个是窗口的名称(字符串类型),另一个是要显示的图像
用于应用固定阈值操作来将灰度图像转换为二值图像
它接收几个参数,包括输入图像、用于分类的阈值、最大值(当像素值超过(或低于,取决于阈值类型)阈值时赋予的值)以及阈值类型
ret, thresh_image = cv2.threshold(src, x,y, Methods)
第一个参数 src 指原图像,原图像应该是灰度图
第二个参数 x 指用来对像素值进行分类的阈值
第三个参数 y 指当像素值高于(有时是小于)阈值时应该被赋予的新的像素值
第四个参数 Methods 指不同的不同的阈值方法
ret 是阈值,thresh_image 是二值化后的图像
常用的阈值类型主要包括:
自动计算最佳阈值
将图像转换为仅包含两个可能像素值的图像(二值图像) 如果像素值高于阈值,则将其设置为最大值(如255) 如果像素值低于或等于阈值,则将其设置为0
与二进制阈值化相反 如果像素值高于阈值,则将其设置为0 如果像素值低于或等于阈值,则将其设置为最大值(如255)
将图像中大于阈值的像素值设置为阈值本身 小于或等于阈值的像素值保持不变
将图像中小于或等于阈值的像素值设置为0 大于阈值的像素值保持不变
与阈值化为0相反 将图像中大于阈值的像素值设置为0 小于或等于阈值的像素值保持不变
cv2.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]])
cv2.boxFilter(src, ddepth, ksize[, dst[, normalize[, borderType]]])
cv2.blur(src, ksize[, dst[, anchor[, borderType]]])
cv2.medianBlur(src, ksize[, dst])
cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]])
当d>0时,d指定了邻域大小且与sigmaSpace无关,否则d正比于sigmaSpace
Sobel()¶用于计算图像梯度的函数,常用于边缘检测。通过 Sobel 算子分别计算图像在水平(x)和垂直(y)方向上的梯度,从而突出图像的边缘特征。 Sobel 算子通过卷积核计算梯度:
[-1 0 1]
[-2 0 2]
[-1 0 1]
[-1 -2 -1]
[ 0 0 0]
[ 1 2 1]
cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]])
src:输入图像(单通道或多通道的灰度/彩色图像)。ddepth:输出图像的深度(数据类型),常用值:cv2.CV_64F(64 位浮点,保留负梯度)cv2.CV_8U(8 位无符号,默认,但会丢失负梯度)dx:x 方向导数的阶数(如 1 表示计算水平梯度)。dy:y 方向导数的阶数(如 1 表示计算垂直梯度)。ksize(可选):Sobel 核的大小,必须是奇数(如 1, 3, 5, 7),默认 3。ksize=1 时使用 3x1 或 1x3 核(无高斯平滑)。ksize=-1 时使用 Scharr 算子(更敏感的边缘检测)。scale(可选):梯度值的缩放因子(默认 1)。delta(可选):添加到结果中的偏移量(默认 0)。borderType(可选):边界填充方式(如 cv2.BORDER_DEFAULT)。# 使用示例:
## 1. 计算水平和垂直梯度
import cv2
import numpy as np
# 读取图像并转为灰度图
image = cv2.imread("image.jpg", cv2.IMREAD_GRAYSCALE)
# 计算 x 和 y 方向的梯度
sobel_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)
sobel_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)
# 转换为绝对值并映射到 8 位无符号
sobel_x_abs = cv2.convertScaleAbs(sobel_x)
sobel_y_abs = cv2.convertScaleAbs(sobel_y)
# 合并梯度
sobel_combined = cv2.addWeighted(sobel_x_abs, 0.5, sobel_y_abs, 0.5, 0)
# 显示结果
cv2.imshow("Original", image)
cv2.imshow("Sobel X", sobel_x_abs)
cv2.imshow("Sobel Y", sobel_y_abs)
cv2.imshow("Combined Sobel", sobel_combined)
cv2.waitKey(0)
cv2.destroyAllWindows()
## 2. 使用 Scharr 算子(更敏感的边缘检测)
scharr_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=-1)
scharr_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=-1)
### 关键注意事项:
# 1. **负梯度处理**:
# - 使用 `cv2.CV_64F` 保留负梯度,再通过 `cv2.convertScaleAbs()` 转换为 8 位。
# - 直接使用 `cv2.CV_8U` 会丢失负梯度信息(边缘方向可能不准确)。
# 2. **梯度方向**:
# - `dx=1, dy=0`:检测垂直边缘(对水平变化敏感)。
# - `dx=0, dy=1`:检测水平边缘(对垂直变化敏感)。
# 3. **噪声影响**:
# - Sobel 对噪声敏感,通常先使用高斯模糊(`cv2.GaussianBlur()`)平滑图像。
cv2.putText(
)
hist = cv2.calcHist([img], [0], None, [256], [0, 256])
注意,除了mask,其他四个参数都要带[]号.后面两个参数基本不用管
import matplotlib.pyplot as plt
创建一个新的图形窗口,特别是需要在同一脚本中创建多个独立的图形时
plt.title('Multiple Line Plots with Different Styles') plt.xlabel('X-axis Label') plt.ylabel('Y-axis Label')
添加图例
添加网格
显示所有当前打开的图形窗口 当调用 plt.show() 时,程序会暂停执行,直到所有的图形窗口都被关闭
用于在 Axes 对象上显示图像数据
参数: X: 要显示的图像数据,通常是二维数组 cmap: 颜色映射表(colormap),用于灰度图像 vmin, vmax: 显示数据范围内的最小值和最大值 aspect: 图像的宽高比控制 interpolation: 插值方法,用于平滑图像
plt.imshow(img, "gray")
图像的二值化,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果
# 在 python 语言中,图像的除法运算可以调用 opencv-python 库中的 divide() 函数进行;
# 导入库
import numpy as np
import cv2
# 定义 X,Y 矩阵
X = np.array([[255,0,75,0],[44,255,100,3]])
Y = np.array([[0,0,25,4],[0,1,50,3]])
# 调用 divide() 函数进行除法运算
result = cv2.divide(X, Y)
# 打印结果
print(result)
# 输出:
# [[ 0 0 3 0]
# [ 0 255 2 1]]
# 结果说明:在保存成图像时,会自动截取(如果大于 255,则取 255)。
# 在 python 语言中,图像的乘法运算可以调用 opencv-python 库中的 multiply() 函数进行。
result = cv2.multiply(X, Y)
# 在 python 语言中,图像的减法运算可以调用 opencv-python 库中的 subtract() 函数进行;
import numpy as np
import cv2
X = np.array([[255,0,75,0],[44,255,100,3]])
Y = np.array([[50,50,50,50],[50,50,50,50]])
result = cv2.subtract(X, Y)
print(result)
# 输出:
# [[205 -50 25 -50]
# [ -6 205 50 -47]]
# 结果说明:在保存成图像时,会自动截取(如果小于 0,则取 0)
import numpy as np
import cv2
X = np.array([[255,0,75,0],[44,255,100,3]])
Y = np.array([[50,50,50,50],[50,50,50,50]])
result = cv2.add(X, Y)
print(result)
# 输出:
# [[305 50 125 50]
# [ 94 305 150 53]]
# 结果说明:在保存成图像时,会自动截取(如果大于255,则取255)
# 相同为0
# 在 python 语言中,异或运算可以使用 ^ 表示
import numpy as np
import cv2
X = cv2.imread('/data/workspace/myshixun/step4/A/image1.jpg', 0)
Y = cv2.imread('/data/workspace/myshixun/step4/A/image2.jpg', 0)
result = X ^ Y
cv2.imwrite("/data/workspace/myshixun/step4/C/result.jpg",result)
print(np.sum(result))
# 在 python 语言中,或运算用 | 表示
result = X | Y
全局阈值法方法就是将图像中低于某个阈值的像素设置为黑色(0),而其他的设置为白色(255)
import cv2
import numpy as np
from matplotlib import pyplot as plt
def hdss_su():
img = cv2.imread('home/OpenCV_2zhih/imgs/timg2.jpg')
# 任务1先将img转灰度
Image = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 再对其使用两个阈值方法对其二值化,阈值为127
ret, BINARY = cv2.threshold(Image,127,255,cv2.THRESH_BINARY)
ret, BINARY_INV = cv2.threshold(Image,127,255,cv2.THRESH_BINARY_INV)
# 传出值Image, BINARY, BINARY_INV
titles = ['Image','BINARY','BINARY_INV']
images = [Image, BINARY, BINARY_INV]
for i in (range(3)):
plt.subplot(1, 3, i + 1)
plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
# plt.savefig("home/OpenCV_2zhih/2z_out/test.png")
return images
Opencv中阈值化操作和自适应阈值化:
cv2.threshold(src, thresh, maxval, type[, dst]) -> retval, dst
例子:ret, binary = cv2.threshold(gray, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)
OTSU为大律法,全局自适应阈值,第二个参数值0可改为任意数字或不写,因为它会被忽略
注:cv2.THRESH_OTSU也可单独使用,不一定要写成和固定阈值算法结合的形式。单独写和结合起来写,都是自适应阈值算法优先
例子:ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_TRIANGLE)
TRIANGLE法,全局自适应阈值,第二个参数值0可改为任意数字但不起作用,适用于单个波峰
注:cv2.THRESH_TRIANGLE也可单独使用,不一定要写成和固定阈值算法结合的形式。单独写和结合起来写,都是自适应阈值算法优先
import cv2
def threshold_us():
image = cv2.imread('home/OpenCV_yz/img/lp.jpg')
# 将图片从BGR颜色空间转换为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 任务1 TRIANGLE自适应阈值
# 使用cv2.threshold函数,其中cv2.THRESH_TRIANGLE表示自动计算一个合适的阈值(基于直方图)
ret, TRIANGLE_img = cv2.threshold(gray,0,255,cv2.THRESH_TRIANGLE)
# 任务2 OTSU自适应阈值
# cv2.THRESH_OTSU也用于自动计算阈值,但算法与THRESH_TRIANGLE不同
# 注意:在使用THRESH_OTSU时,通常不需要手动指定阈值参数(第一个参数),因为它会被忽略
ret, OTSU_img = cv2.threshold(gray,0,255,cv2.THRESH_OTSU)
# 任务3 TRUNC截断阈值(200)
# 对于大于200的像素值,它们会被截断为200;小于200的像素值保持不变
# 注意:THRESH_TRUNC模式下,maxval参数(这里是255)实际上不会被用到,但仍需设置
ret, TRUNC_img = cv2.threshold(gray,200,255,cv2.THRESH_TRUNC)
# 任务4 TOZERO归零阈值(100)
# 对于小于100的像素值,它们会被设置为0;大于或等于100的像素值保持不变
ret, TOZERO_img = cv2.threshold(gray,100,255,cv2.THRESH_TOZERO)
# 将处理后的图像保存到指定的文件夹中
cv2.imwrite('home/OpenCV_yz/img_out/TRIANGLE_img.jpg',TRIANGLE_img)
cv2.imwrite('home/OpenCV_yz/img_out/OTSU_img.jpg',OTSU_img)
cv2.imwrite('home/OpenCV_yz/img_out/TRUNC_img.jpg',TRUNC_img)
cv2.imwrite('home/OpenCV_yz/img_out/TOZERO__img.jpg',TOZERO_img)
# 返回处理后的图像
return TRIANGLE_img, OTSU_img, TRUNC_img, TOZERO_img
高斯平滑即采用高斯卷积核对图像矩阵进行卷积操作 高斯卷积核是一个近似服从高斯分布的矩阵,随着距离中心点的距离增加,其值变小。这样进行平滑处理时,图像矩阵中锚点处像素值权重大,边缘处像素值权重小
dst = cv2.GaussianBlur(src,ksize,sigmaX,sigmay,borderType)
参数说明:
src: 输入图像矩阵,可为单通道或多通道,多通道时分别对每个通道进行卷积
dst:输出图像矩阵,大小和数据类型都与src相同
ksize:高斯卷积核的大小,宽,高都为正奇数,且可以不相同,格式为(宽,高)
核大小:核越大,参与卷积的像素越多,平滑效果越明显,但计算量增加
奇偶性:必须为奇数以确保存在明确的中心点,避免核偏移。若输入偶数,OpenCV 会报错
方向性:若宽度 ≠ 高度(如 (5,3)),水平和垂直方向的平滑强度不同,可能导致图像在特定方向更模糊
sigmaX: 一维水平方向高斯卷积核的标准差
标准差越大:高斯分布越平缓,更多周围像素参与计算,平滑效果更强
默认值:若未指定(sigmaX=0),OpenCV 会根据 ksize 自动计算(公式:sigma = 0.3*((ksize-1)/2 - 1) + 0.8)
sigmaY: 一维垂直方向高斯卷积核的标准差
默认值为0,表示与sigmaX相同
borderType:填充边界类型
cv2.BORDER_REPLICATE:复制边缘像素值
cv2.BORDER_CONSTANT:填充固定值(如 0,默认黑色)
cv2.BORDER_REFLECT:镜像反射边缘像素
见'高斯滤波.py'
高斯卷积核,对卷积框中像素值赋予不同权重,而均值平滑赋予相同权重 opencv的boxFilter()函数和blur()函数都能用来进行均值平滑。
cv2.boxFilter(src,ddepth,ksize,dst,anchor,normalize,borderType)
dst=cv2.boxFilter(src,ddepth,ksize,anchor,normalize,borderType)
参数说明:
src: 输入图像对象矩阵,
ddepth:输出图像的位深度(数据格式)
-1:与输入图像深度相同。
ksize:高斯卷积核的大小,必须为正奇数,格式为(宽,高)
同上
dst:输出图像矩阵,大小和数据类型都与src相同
anchor:卷积核锚点,默认(-1,-1)表示卷积核的中心位置
normalize:是否归一化
True(默认):计算均值(均值平滑),输出为均值滤波结果
False:计算邻域像素和(积分图像),输出为邻域像素和,可用于快速计算 Haar 特征
borderType:填充边界类型
同上
cv2.blur(src,ksize,dst,anchor,borderType) dst=cv2.blur(src,ksize,anchor,borderType) 参数说明: src: 输入图像对象矩阵,可以为单通道或多通道 ksize:高斯卷积核的大小,格式为(宽,高) dst:输出图像矩阵,大小和数据类型都与src相同 anchor:卷积核锚点,默认(-1,-1)表示卷积核的中心位置 borderType:填充边界类型
与高斯平滑相比:边缘模糊更严重,简单降噪,计算效率高 见'均值滤波.py'
是对核中所有像素值排序得到中间值,用该中间值来代替锚点值。 opencv中利用medianBlur()来进行中值平滑。
cv2.medianBlur(src,ksize,dst)
dst=cv2.medianBlur(src,ksize)
参数说明:
src: 输入图像对象矩阵,可以为单通道或多通道
ksize:核的大小,格式为 3
必须为正奇数
dst:输出图像矩阵,大小和数据类型都与src相同
优点:对椒盐噪声(随机黑白点)效果显著,且能保留边缘。 缺点:对高斯噪声(连续渐变噪声)效果有限,且计算复杂度较高(需排序) 见'排序统计滤波.py'
双边滤波是一种非线性滤波方法,相比于上面几种平滑算法,双边滤波在平滑的同时还能保持图像中物体的轮廓信息 它通过结合空间距离权重(空间域)和像素值相似性权重(值域)实现这一目标 双边滤波在高斯平滑的基础上引入了灰度值相似性权重因子,所以在构建其卷积核核时,要同时考虑空间距离权重和灰度值相似性权重 在进行卷积时,每个位置的邻域内,根据和锚点的距离d构建距离权重模板,根据和锚点灰度值差异r构建灰度值权重模板,结合两个模板生成该位置的卷积核。
opencv中的bilateralFilter()函数实现了双边滤波,其参数对应如下:
dst = cv2.bilateralFilter(src,d,sigmaColor,sigmaSpace,borderType) 参数说明: src: 输入图像对象矩阵,可以为单通道或多通道 d: 用来计算卷积核的领域直径,如果d<=0,从sigmaSpace自动计算d 邻域大小:d 越大,参与滤波的像素越多,但计算量显著增加 推荐值:通常取 5~9,过大可能导致过度平滑 与 sigmaSpace 的关系:若 d > 0,邻域直径为 d,否则邻域直径与 sigmaSpace 成正比 sigmaColor:值域(颜色空间)的标准差 值越大:颜色差异较大的像素也会被混合,可能导致颜色区域过度平滑,边缘保留能力下降 值越小:仅颜色相近的像素参与滤波,边缘保留更好,但去噪能力减弱 推荐值:通常取 30~100,需根据图像噪声水平调整 sigmaSpace: 空间域(坐标空间)的标准差 值越大:颜色相近的较远的像素对滤波结果影响增强,从而使更大的区域中足够相似的颜色获取相同的颜色,平滑范围扩大,但可能导致边缘模糊 值越小:仅邻近像素参与滤波,边缘保留更好,但去噪能力减弱 推荐值:通常取 30~100,需与 sigmaColor 协同调整。
见'平滑处理.py'
直方图是一种统计报告图,形式上是一个个的长条形,长条形的面积表示频数,高度表示频数组距,宽度表示组距。当宽度相同时,一般就用长条形长度表示频数
直方图反映了图像像素分布的统计特性
2. 基本性质
以图形化参数来显示图片曝光精确度的手段,其描述的是图片显示范围内影像的灰度分布曲线
它可以帮助分析图片的曝光水平等一些信息。直方图的左边显示了图像的阴影信息``中间显示了图像的中间色调信息``右边显示了图像的高亮信息
3. 重要性质:
反映了图像中的灰度分布规律。它描述每个灰度级具有的像素个数,但不包含这些像素在图像中的位置信息
直方图和图像之间的关系是多对一的关系。任何一幅特定的图像都有唯一的直方图与之对应,但不同的图像可以有相同的直方图。
如果一幅图像有两个不相连的区域组成,并且每个区域的直方图已知,则整幅图像的直方图是该两个区域的直方图之和
4. 应用
根据直方图的形态可以大致推断图像质量的好坏。由于图像包含有大量的像元,其像元灰度值的分布应符合概率统计分布规律。假定像元的灰度值是随机分布的,那么其直方图应该是正态分布
图像的灰度值是离散变量,因此直方图表示的是离散的概率分布。若以各灰度级的像元数占总像元数的比例值为纵坐标轴做出图像的直方图,将直方图中各条形的最高点连成一条外轮廓线,纵坐标的比例值即为某灰度级出现的概率密度,轮廓线可近似看成图像相应的连续函数的概率分布曲线
plt 绘制直方图和线性图
plt.hist(data,bins=30, normed=0, facecolor="red", alpha=0.7) 参数 作用 data 必选参数,绘图数据 bins 直方图的长条形数目,可选项,默认为10 normed 是否将得到的直方图向量归一化,可选项,默认为0,代表不归一化,显示频数。normed=1,表示归一化,显示频率。 facecolor 长条形的颜色 edgecolor 长条形边框的颜色 alpha 透明度
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
def student(data, x, y):
'''
根据输入数据将直方图与线形图绘制在同一面板中,并设置直方图为红色,线形图为蓝色
:return: None
'''
# 创建一个新的图形,设置figsize为(10, 10)
plt.figure(figsize=(10, 10))
# 绘制直方图
plt.hist(data, facecolor="red",alpha=0.7)
# 绘制线形图
plt.plot(x, y, color="blue")
# 保存图形
plt.savefig('Task4/img/T1.png')
cv2 绘制直方图 cv2.calcHist([img], [0], None, [256], [0,256]) 见'绘制直方图.py'
plt.hist2d()
见'灰度直方图的计算.py'
直方图均衡化是灰度变换的一个重要应用,它高效且易于实现,广泛应用于图像增强处理中
图像的像素灰度变化是随机的,直方图的图形高低不齐,直方图均衡化就是用一定的算法使直方图大致平和
均衡化处理后的图象只能是近似均匀分布。本质是扩大量化间隔,而减少量化级别,
因此,原来灰度不同的像素经处理后可能变的相同,形成了一片的相同灰度的区域,各区域之间有明显的边界,从而出现了伪轮廓
灰度直方图均衡化的算法,简单地说,就是把直方图的每个灰度级进行归一化处理,求每种灰度的累积分布,得到一个映射的灰度映射表,然后根据相应的灰度值来修正原图中的每个像素
equalizeHist()
见 '直方图均衡化.py'
基于RGB,HSV
OTSU
基于边缘的分割方法(Canny 边缘检测,Sobel 算子)
基于区域的分割方法(区域生长,分水岭算法)
基于聚类的分割方法(K-Means 聚类)
基于深度学习的分割方法
基于图论的分割方法(GrabCut)
import cv2
from matplotlib import pyplot as plt
import numpy as np
M=cv2.imread('/data/bigfiles/M.jpg')#BGR
M_rgb=cv2.cvtColor(M,cv2.COLOR_BGR2RGB)
R=M_rgb[:,:,0]
G=M_rgb[:,:,1]
B=M_rgb[:,:,2]
M_hsv=cv2.cvtColor(M_rgb,cv2.COLOR_RGB2HSV)
# 分割黄色花朵部分
# 定义黄色的HSV范围(可以根据实际情况调整)
lower_yellow = np.array([20, 100, 100])
upper_yellow = np.array([30, 255, 255])
# 创建掩膜
mask = cv2.inRange(M_hsv, lower_yellow, upper_yellow)
# 应用掩膜获取黄色部分
E = cv2.bitwise_and(M_rgb, M_rgb, mask=mask)
# 计算E的像素值总和
sum_pixels = np.sum(E)
# 显示图像
plt.figure(figsize=(15, 10))
# 显示原图
plt.subplot(2, 3, 1)
plt.imshow(M_rgb)
plt.title('M')
plt.axis('off')
# 显示R分量图
plt.subplot(2, 3, 2)
plt.imshow(R, cmap='Reds')
plt.title('R')
plt.axis('off')
# 显示G分量图
plt.subplot(2, 3, 3)
plt.imshow(G, cmap='Greens')
plt.title('G')
plt.axis('off')
# 显示B分量图
plt.subplot(2, 3, 4)
plt.imshow(B, cmap='Blues')
plt.title('B')
plt.axis('off')
# 显示HSV图
plt.subplot(2, 3, 5)
# 将HSV转换为RGB以便显示(因为Matplotlib不直接支持HSV显示)
M_hsv_rgb = cv2.cvtColor(M_hsv, cv2.COLOR_HSV2RGB)
plt.imshow(M_hsv_rgb)
plt.title('HSV')
plt.axis('off')
# 显示分割后的E图
plt.subplot(2, 3, 6)
plt.imshow(E)
plt.title('E')
plt.axis('off')
plt.tight_layout()
plt.show()
# 打印E的像素值总和
print(f"SUM:{sum_pixels}")
import cv2
import numpy as np
from matplotlib import pyplot as plt
M = cv2.imread('M.jpg', cv2.IMREAD_GRAYSCALE) # 读取为灰度图
edges = cv2.Canny(M, 100, 200) # Canny边缘检测
plt.imshow(edges, cmap='gray')
plt.title('Canny Edge Detection')
plt.axis('off')
plt.show()
import cv2
import numpy as np
from matplotlib import pyplot as plt
M = cv2.imread('M.jpg')
gray = cv2.cvtColor(M, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# 去除噪声
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
# 确定背景区域
sure_bg = cv2.dilate(opening, kernel, iterations=3)
# 确定前景区域
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)
# 找到未知区域
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)
# 标记标签
ret, markers = cv2.connectedComponents(sure_fg)
markers = markers + 1
markers[unknown == 255] = 0
# 应用分水岭算法
markers = cv2.watershed(M, markers)
M[markers == -1] = [255, 0, 0] # 标记边界为红色
plt.imshow(cv2.cvtColor(M, cv2.COLOR_BGR2RGB))
plt.title('Watershed Segmentation')
plt.axis('off')
plt.show()
import cv2
import numpy as np
from matplotlib import pyplot as plt
M = cv2.imread('M.jpg')
Z = M.reshape((-1, 3)) # 转换为二维数组,形状为 (像素数, 3)
Z = np.float32(Z) # 转换为float32类型
# 定义K-Means参数
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 3 # 聚类数量
ret, label, center = cv2.kmeans(Z, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
# 将聚类结果转换回图像
center = np.uint8(center)
res = center[label.flatten()]
res2 = res.reshape((M.shape))
plt.imshow(cv2.cvtColor(res2, cv2.COLOR_BGR2RGB))
plt.title('K-Means Segmentation')
plt.axis('off')
plt.show()
import cv2
import numpy as np
from matplotlib import pyplot as plt
M = cv2.imread('M.jpg')
mask = np.zeros(M.shape[:2], np.uint8)
# 定义矩形区域(包含前景)
bgd_model = np.zeros((1, 65), np.float64)
fgd_model = np.zeros((1, 65), np.float64)
rect = (50, 50, 450, 290) # 矩形坐标 (x, y, w, h)
# 应用GrabCut算法
cv2.grabCut(M, mask, rect, bgd_model, fgd_model, 5, cv2.GC_INIT_WITH_RECT)
# 创建掩膜
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
result = M * mask2[:, :, np.newaxis]
plt.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
plt.title('GrabCut Segmentation')
plt.axis('off')
plt.show()
# 低通滤波
def ideal_low_pass_filter(image, cutoff):
# 计算图像的二维傅里叶变换
f = np.fft.fft2(image)
# 将傅里叶变换的低频分量移到频谱的中心
fshift = np.fft.fftshift(f)
# 获取图像的行数和列数
rows, cols = image.shape
# 计算频谱的中心位置
crow, ccol = rows // 2, cols // 2
# 创建一个与图像大小相同的零矩阵作为掩码
mask = np.zeros((rows, cols), np.uint8)
# 在掩码的中心区域设置截止频率的范围,并将该区域的值设为1
mask[crow - cutoff:crow + cutoff, ccol - cutoff:ccol + cutoff] = 1
# 将频谱与掩码相乘,实现低通滤波
fshift_filtered = fshift * mask
# 将频谱的低频分量移回原始位置
f_ishift = np.fft.ifftshift(fshift_filtered)
# 计算逆傅里叶变换,将频域数据转换回空间域
img_back = np.fft.ifft2(f_ishift)
# 取逆傅里叶变换结果的绝对值,得到空间域图像
img_back = np.abs(img_back)
return img_back
# 高通滤波
def ideal_high_pass_filter(image, cutoff):
f = np.fft.fft2(image)
fshift = np.fft.fftshift(f)
rows, cols = image.shape
crow, ccol = rows // 2, cols // 2
# 创建一个与图像大小相同的全1矩阵作为掩码
mask = np.ones((rows, cols), np.uint8)
# 在掩码的中心区域设置截止频率的范围,并将该区域的值设为0
mask[crow - cutoff:crow + cutoff, ccol - cutoff:ccol + cutoff] = 0
fshift_filtered = fshift * mask
f_ishift = np.fft.ifftshift(fshift_filtered)
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back)
return img_back