【学习笔记】OpenCv图像处理基础(上)

1 图像基础知识

1.1 数字图像

一幅二维图像可以由一个矩阵数组表示,我们可以把它理解为一个二元函数 f ( x , y ) f(x,y) f(x,y),其中 x x x y y y是空间坐标, f f f表示该坐标处的值,也就是图像在该点的强度或者灰度

常见的成像方式有:

名称波长性质应用
γ \gamma γ射线 < 1 0 − 10 <10^{-10} <1010从原子核内发出来的,穿透能力强,对生物的破坏力大大脑生理信号EGG
χ \chi χ射线 ( 10 − 0.01 ) × 1 0 − 9 (10-0.01)×10^{-9} (100.01)×109不同部位对其吸收率不同CT
紫外线 ( 380 − 10 ) × 1 0 − 9 (380-10)×10^{-9} (38010)×109化学效应,荧光效应生物医学领域
可见光 ( 7.8 − 3.8 ) × 1 0 − 7 (7.8-3.8)×10^{-7} (7.83.8)×107光线照在物体上,反射到人眼中
红外线 ( 1000 − 0.78 ) × 1 0 − 6 (1000-0.78)×10^{-6} (10000.78)×106自然界一切物体都可以辐射红外线红外图像;红外测温
微波 0.1 c m − 1 m 0.1cm-1m 0.1cm1m辐射雷达;通讯系统;微波影像
射频 0.1 c m − 3000 m 0.1cm-3000m 0.1cm3000m电视;无线电广播;医学成像

1.2 图像属性

图像格式

BMP:未经压缩,文件较大;
JPEG:有损压缩,互联网上广泛使用;
GIF:可以是动画,支持透明背景,但色域不太广;
PNG:压缩比高于GIF,支持透明图像,可通过Alpha通道调节透明度;
TIFF:图像格式复杂,存储信息丰富,用于印刷;

图像的尺寸以像素为单位,灰度像素值范围在0~255之间,0代表黑色,255代表白色。

图像分辨率:单位长度中所具有的像素数量。
通道数:图像的位深度,图像中每个像素值所占的二进制数。越大可以表示的颜色越多,色彩越丰富逼真。
八位:单通道,灰度图,灰度值范围为0~255;
24位:三通道RGB,3*8=24;
32位:四通道:RGB+透明度Alpha通道;
颜色空间:RGB、HSV(色调;饱和度;明度)、HSI(色调;饱和度;强度)、CMYK(青;品;黄;黑)

1.3 图像操作

灰度转换:将三通道转化为单通道图像cvt.cvtColor() g r a y = B × 0.114 + G × 0.587 + R ∗ 0.299 gray = B×0.114+G×0.587+R*0.299 gray=B×0.114+G×0.587+R0.299

BGR转换为RGB:用cv读取图像时是按照BGR顺序存储的,若用plot画图需要将BGR转换为RGB。

通道分离:将彩色图像分离成B、G、R三个单通道图像cv2.split()
通道合并:对B、G、R三个单通道进行修改,最后将修改后的单通道合并成彩色图像cv2.merge()

直方图:直方图描述了图像中每个亮度值的像素数,左侧为纯黑、较暗;右侧为较亮、纯白。cv2.calcHist()


2 图像基本操作

2.1 绘图

绘制线段:

绘制矩形:

绘制圆:

绘制椭圆:

绘制多边形:

添加文字


2.2 图像几何变换

图像平移


图像缩放:下采样,上采样。

插值方法:最近邻插值;双线性插值;
图像旋转

仿射变换

透视变换

2.3 图像滤波与增强

高通滤波器用于边缘检测,低通滤波器用于图像平滑去噪

邻域算子:给定像素周围像素值决定给定像素的最终输入的一种算子。线性滤波是一种常用的邻域算子,其像素输出值取决于输入像素的加权和。
g ( i , j ) = ∑ k , l f ( i + k , j + l ) h ( k , l ) g(i,j)=\sum_{k,l}f(i+k,j+l)h(k,l) g(i,j)=k,lf(i+k,j+l)h(k,l)
线性滤波—方框滤波


线性滤波—均值滤波

线性滤波—高斯滤波


非线性滤波—中值滤波

非线性滤波—双边滤波

直方图均衡化


Gamma变化

2.4 图像形态学操作

图像腐蚀


图像膨胀

开运算:先腐蚀后膨胀把细微连在一起的两块目标分开。

闭运算:先膨胀再腐蚀,把细微连在一块的图封闭在一块。

形态学梯度

顶帽和黑帽

3 图像分割

图像分割是指将若干图像分成具有相似性质区域的过程,主要有基于阈值、基于区域、基于边缘、基于聚类、基于图论和基于深度学习的图像分割方法。 图像分割分为语义分割和实例分割。 分割的原则:使划分后的子图在内部保持相似度最大,而子图之间的相似度保持最小。 ## 3.1 分割方法 **固定阈值图像分割**: 五种阈值方法: **自动阈值分割**: **迭代法阈值分割**:
import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
def best_thresh(img):
    img_array = np.array(img).astype(np.float32)#转化成数组
    I=img_array
    zmax=np.max(I)
    zmin=np.min(I)
    tk=(zmax+zmin)/2#设置初始阈值
    print(tk)
    #根据阈值将图像进行分割为前景和背景,分别求出两者的平均灰度zo和zb
    b=1
    m,n=I.shape
    while b==1:
        ifg=0
        ibg=0
        fnum=0
        bnum=0
        # 遍历图像上每一点
        for i in range(1,m):
             for j in range(1,n):
                tmp=I[i,j]
                if tmp>=tk:
                    ifg=ifg+1
                    fnum=fnum+int(tmp)#前景像素的个数以及像素值的总和
                else:
                    ibg=ibg+1
                    bnum=bnum+int(tmp)#背景像素的个数以及像素值的总和
        #计算前景和背景的平均值
        zo=int(fnum/ifg)
        zb=int(bnum/ibg)
        if tk==int((zo+zb)/2):#若前景和背景的平均值等于当前阈值,退出循环
            b=0
        else:
            tk=int((zo+zb)/2)#否者更新阈值
    return tk
img = cv2.imread("./image/bird.png")
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
gray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
img = cv2.resize(gray,(200,200))#大小
yvzhi=best_thresh(img)
ret1, th1 = cv2.threshold(img, yvzhi, 255, cv2.THRESH_BINARY)
print(ret1)
plt.imshow(th1,cmap=cm.gray)
plt.show()

结果:

otsu大津法:是一种基于全局阈值的自适应方法,使的分割结果有最大类间方差。

3.2 边缘提取

图像梯度


模板卷积

梯度算子:是一阶导数算子






Canny边缘检测算法:先平滑后求导的方法

边缘检测性能评价指标:

  1. 好的信噪比,即将非边缘点判定为边缘点的概率要低,将边缘点判为非边缘点的概 率要低;
  2. 高的定位性能,即检测出的边缘点要尽可能在实际边缘的中心;
  3. 对单一边缘仅有唯一响应,即单个边缘产生多个响应的概率要低,并且虚假响应边缘应该得到最大抑制。

3.3 连通区域分析

Two-Pass 算法


代码实现:
Tow-pass代码

区域生长算法


区域生长好坏的决定因素有:初始点(种子点)的选取、生长准则、终止条件。
代码实现:
区域生长代码

分水岭算法:给每个孤立的山谷(局部最小值)不同颜色的水(标签),当水涨起来,根据周围的山峰(梯度),不同的山谷也就是不同的颜色会开始合并,要避免山谷合并,需要在水要合并的地方建立分水岭,直到所有山峰都被淹没,所创建的分水岭就是分割边界线,这就是分水岭的原理。

# import cv2
"""
完成分水岭算法步骤:
1、加载原始图像
2、阈值分割,将图像分割为黑白两个部分
3、对图像进行开运算,即先腐蚀在膨胀
4、对开运算的结果再进行 膨胀,得到大部分是背景的区域
5、通过距离变换 Distance Transform 获取前景区域
6、背景区域sure_bg 和前景区域sure_fg相减,得到即有前景又有背景的重合区域
7、连通区域处理
8、最后使用分水岭算法
"""
import cv2
import numpy as np

# Step1. 加载图像
img = cv2.imread('image/yezi.jpg')
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Step2.阈值分割,将图像分为黑白两部分
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# cv2.imshow("thresh", thresh)

# Step3. 对图像进行“开运算”,先腐蚀再膨胀
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
# cv2.imshow("opening", opening)

# Step4. 对“开运算”的结果进行膨胀,得到大部分都是背景的区域
sure_bg = cv2.dilate(opening, kernel, iterations=3)
cv2.imshow("sure_bg", sure_bg)
cv2.waitKey(0)
cv2.destroyAllWindows()

# Step5.通过distanceTransform获取前景区域
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)  # DIST_L1 DIST_C只能 对应掩膜为3    DIST_L2 可以为3或者5
cv2.imshow("dist_transform", dist_transform)
cv2.waitKey(0)
cv2.destroyAllWindows()
print(dist_transform.max())
ret, sure_fg = cv2.threshold(dist_transform, 0.1 * dist_transform.max(), 255, 0)

# Step6. sure_bg与sure_fg相减,得到既有前景又有背景的重合区域   #此区域和轮廓区域的关系未知 
sure_fg = np.uint8(sure_fg)
unknow = cv2.subtract(sure_bg, sure_fg)
cv2.imshow("unknow", unknow)
cv2.waitKey(0)
cv2.destroyAllWindows()

# Step7. 连通区域处理
ret, markers = cv2.connectedComponents(sure_fg,connectivity=8) #对连通区域进行标号  序号为 0 - N-1 
#print(markers)
print(ret)
markers = markers + 1           #OpenCV 分水岭算法对物体做的标注必须都 大于1 ,背景为标号 为0  因此对所有markers 加1  变成了  1  -  N
#去掉属于背景区域的部分(即让其变为0,成为背景)
# 此语句的Python语法 类似于if ,“unknow==255” 返回的是图像矩阵的真值表。
markers[unknow==255] = 0   

# Step8.分水岭算法
markers = cv2.watershed(img, markers)  #分水岭算法后,所有轮廓的像素点被标注为  -1 
#print(markers)

img[markers == -1] = [0, 0, 255]   # 标注为-1 的像素点标 红
cv2.imshow("dst", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值