山东大学数字图像处理实验(六) 计算机学院

本实验为计算机科学与技术学院计算机专业大四上限选课,2023-2024-1年度课程实验,较以往实验内容发生较大变化
本实验使用vscode,python语言,需要提前安装opencv,具体方法请自行搜索。

实验6:图像统计特征

基于颜色分布的交互图像分割

基于由用户交互笔刷标记的前、背景像素(图中黄绿区域),计算前、背景的颜色分布,并用于估计未标记像素属于前景和背景的概率。
颜色分布可以用直方图或者高斯混合模型( GMM )表示。如果用 GMM ,可以基于 OpenCV 的实现估计 GMM 参数。

 

import cv2
import numpy as np
from sklearn.mixture import GaussianMixture as GM

img = cv2.imread('1.jpg')
# 使用cv2的resize方法调整图片大小,将图片的长和宽都缩小为原来的0.5倍,然后赋给变量img  
img = cv2.resize(img, (0, 0), fx=0.5, fy=0.5)

l = np.zeros(img.shape[:2], dtype=np.uint8)
f, b = 1, 2

d, m = False, f
o = np.zeros_like(img)
fc, bc = (0, 255, 0), (255, 0, 0)

def draw(e, x, y, f, p):
    global d, m, o, l
    if e == cv2.EVENT_LBUTTONDOWN:#鼠标左键按下
        d = True
        c, lbl = (fc, f) if m == f else (bc, b)# 如果m等于f,则c为fc,否则为bc;lbl始终为f或b 
        cv2.circle(o, (x, y), 10, c, -1)
        cv2.circle(l, (x, y), 10, lbl, -1)# 在图像l上以(x,y)为圆心画一个半径为10的圆,颜色为lbl
    elif e == cv2.EVENT_MOUSEMOVE and d:
        c, lbl = (fc, f) if m == f else (bc, b)
        cv2.circle(o, (x, y), 10, c, -1)# 在图像o上以(x,y)为圆心画一个半径为10的圆,颜色为c
        cv2.circle(l, (x, y), 10, lbl, -1)# 在图像l上以(x,y)为圆心画一个半径为10的圆,颜色为lbl
    elif e == cv2.EVENT_LBUTTONUP:
        d = False

def perform_gcut(img, l):
    fpx, bpx = img[l == f].reshape(-1, 3), img[l == b].reshape(-1, 3)
     # 创建两个高斯混合模型(Gaussian Mixture Model,GMM),分别是gmf和gmb。每个模型有5个组件(即高斯分布),并且协方差类型为'full',表示每个组件都有独立的协方差矩阵。
    gmf, gmb = GM(n_components=5, covariance_type='full'), GM(n_components=5, covariance_type='full')
    gmf.fit(fpx) # 使用fpx训练gmf模型,使用bpx训练gmb模型。
    gmb.fit(bpx)
    pf, pb = gmf.score_samples(img.reshape(-1, 3)), gmb.score_samples(img.reshape(-1, 3))
    pf, pb = np.exp(pf), np.exp(pb)# 计算整个图像img对于gmf和gmb模型的得分,即每个像素属于某个高斯分布的概率。
    # 对得分进行指数化,使得概率值在合理的范围内。
    pm = pf / (pf + pb)# 计算每个像素属于gmf模型的概率,即前景(标记为f的区域)的概率。
    th = 0.5# 定义一个阈值th,用于分割前景和背景。
    rm = np.where(pm > th, 1, 0)# 使用条件语句将图像分割为前景(标记为1)和背景(标记为0)。
    rm = rm.reshape(img.shape[:2])# 将分割后的二维数组重塑为原始图像的形状,但是只有两个维度(高度和宽度),没有颜色通道。 
    ri = np.zeros_like(img)# 创建一个与原始图像形状相同但所有像素值为0的新图像ri。 
    ri[rm == 0], ri[rm == 1] = [0, 0, 0], [255, 255, 255]  # 根据分割结果rm,将新图像ri中属于背景的部分设置为黑色(RGB值为[0, 0, 0]),属于前景的部分设置为白色(RGB值为[255, 255, 255])。  
    se = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    cv2.dilate(ri, se, ri)
    cv2.imshow('mask', ri)

cv2.namedWindow('input')
cv2.setMouseCallback('input', draw)

while True:
    mi = cv2.addWeighted(img, 1, o, 0.5, 0)
    cv2.imshow('input', mi)
    k = cv2.waitKey(10) & 0xFF
    if k == 27:
        break
    elif k == ord('f'):
        m = f
    elif k == ord('b'):
        m = b
    elif k == ord('n'):
        perform_gcut(img, l)

cv2.destroyAllWindows()


  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值