图像分割恢复方法

传统的图像分割方法主要依赖于图像的灰度值、纹理、颜色等特征,通过不同的算法将图像分割成多个区域。这些方法通常可以分为以下几类:
1.基于阈值的方法
2.基于边缘的方法
3.基于区域的方法
4.基于聚类的方法
下面详细介绍这些方法及其示例代码。

1. 基于阈值的方法

基于阈值的方法是最简单的图像分割方法之一,通过设定一个或多个阈值,将图像分为前景和背景。

示例代码(全局阈值)

import cv2
import numpy as np
from matplotlib import pyplot as plt# 读取灰度图像
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)# 应用全局阈值分割
_, thresh = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)# 显示结果
plt.subplot(1, 2, 1)
plt.title('Original Image')
plt.imshow(image, cmap='gray')plt.subplot(1, 2, 2)
plt.title('Global Thresholding')
plt.imshow(thresh, cmap='gray')plt.show()

示例代码(Otsu’s 阈值)

_, otsu_thresh = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)plt.subplot(1, 2, 1)
plt.title('Original Image')
plt.imshow(image, cmap='gray')plt.subplot(1, 2, 2)
plt.title('Otsu Thresholding')
plt.imshow(otsu_thresh, cmap='gray')plt.show()

2. 基于边缘的方法

基于边缘的方法通过检测图像中的边缘,将图像分割成不同的区域。
示例代码(Canny 边缘检测)

edges = cv2.Canny(image, 100, 200)plt.subplot(1, 2, 1)
plt.title('Original Image')
plt.imshow(image, cmap='gray')plt.subplot(1, 2, 2)
plt.title('Edge Detection')
plt.imshow(edges, cmap='gray')plt.show()

3. 基于区域的方法

基于区域的方法通过区域生长、区域合并等算法,根据像素相似性将图像分割成不同的区域。
示例代码(区域生长)

import cv2
import numpy as np
from matplotlib import pyplot as pltdef region_growing(img, seed):h, w = img.shapesegmented_img = np.zeros_like(img)stack = [seed]while len(stack) > 0:x, y = stack.pop()if segmented_img[x, y] == 0 and img[x, y] > 128:segmented_img[x, y] = 255if x > 0:stack.append((x - 1, y))if x < h - 1:stack.append((x + 1, y))if y > 0:stack.append((x, y - 1))if y < w - 1:stack.append((x, y + 1))return segmented_img# 读取灰度图像
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)seed = (100, 100)  # 种子点
segmented_img = region_growing(image, seed)plt.subplot(1, 2, 1)
plt.title('Original Image')
plt.imshow(image, cmap='gray')
plt.subplot(1, 2, 2)
plt.title('Region Growing')
plt.imshow(segmented_img, cmap='gray')
plt.show()

4. 基于聚类的方法

基于聚类的方法通过聚类算法(如K均值聚类)将图像中的像素分为不同的簇,从而实现图像分割。
示例代码(K均值聚类)

import cv2
import numpy as np
from matplotlib import pyplot as plt# 读取图像并转换为二维数据
image = cv2.imread('image.jpg')
Z = image.reshape((-1, 3))
Z = np.float32(Z)# 定义K均值参数
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)# 转换回uint8数据类型,并重塑回原始图像
center = np.uint8(center)
res = center[label.flatten()]
segmented_image = res.reshape((image.shape))# 显示结果
plt.subplot(1, 2, 1)
plt.title('Original Image')
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))plt.subplot(1, 2, 2)
plt.title('Segmented Image (K = 3)')
plt.imshow(cv2.cvtColor(segmented_image, cv2.COLOR_BGR2RGB))plt.show()

5. 基于图论的方法

基于图论的方法通过将图像看作一个图,其中像素是图的节点,边的权重表示像素之间的相似性。常见的图论方法有图割算法(Graph Cut)和分水岭算法(Watershed)。

分水岭算法步骤

  • 预处理:为了减小噪声影响,通常对图像进行平滑处理。
  • 计算梯度:使用梯度运算子(如Sobel算子)计算图像的梯度,得到梯度幅值图。
  • 标记前景和背景:通过一些方法(如阈值分割或形态学操作)对前景和背景进行标记。
  • 应用分水岭算法:基于标记的前景和背景,对图像应用分水岭算法进行分割。

详细代码实现
以下是一个详细的Python代码示例,展示如何使用OpenCV实现分水岭算法进行图像分割:

import cv2
import numpy as np
from matplotlib import pyplot as plt# 读取图像
image = cv2.imread('image.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 1. 预处理:平滑图像,减小噪声
blurred = cv2.GaussianBlur(gray, (5, 5), 0)# 2. 计算梯度
grad_x = cv2.Sobel(blurred, cv2.CV_64F, 1, 0, ksize=3)
grad_y = cv2.Sobel(blurred, cv2.CV_64F, 0, 1, ksize=3)
gradient = cv2.addWeighted(grad_x, 0.5, grad_y, 0.5, 0)# 3. 二值化
_, binary = cv2.threshold(gradient, 50, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)# 4. 形态学操作,去除小块噪声
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
closed = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel, iterations=2)# 5. 距离变换
dist_transform = cv2.distanceTransform(closed, cv2.DIST_L2, 5)
_, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(closed, sure_fg)# 6. 标记前景和背景
_, markers = cv2.connectedComponents(sure_fg)# 增加1,以便背景为1
markers = markers + 1# 未知区域标记为0
markers[unknown == 255] = 0# 7. 应用分水岭算法
markers = cv2.watershed(image, markers)
image[markers == -1] = [0, 0, 255]# 显示结果
plt.subplot(2, 2, 1), plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)), plt.title('Original Image')
plt.subplot(2, 2, 2), plt.imshow(gradient, cmap='gray'), plt.title('Gradient')
plt.subplot(2, 2, 3), plt.imshow(closed, cmap='gray'), plt.title('Closed')
plt.subplot(2, 2, 4), plt.imshow(markers, cmap='gray'), plt.title('Markers')
plt.show()

代码解释
1.读取图像和预处理:

  • 读取图像并转换为灰度图。
  • 使用高斯模糊平滑图像,减小噪声。

2.计算梯度:

  • 使用Sobel算子计算图像的梯度。
  • 将x方向和y方向的梯度组合在一起,得到梯度幅值图。

3.二值化:

  • 使用全局阈值(Otsu方法)对梯度图进行二值化。

4.形态学操作:

  • 使用闭运算去除小块噪声,填补前景对象中的小孔。

5.距离变换:

  • 计算前景对象的距离变换。
  • 根据距离变换结果,确定前景对象的中心区域。

6.标记前景和背景:

  • 使用连通组件标记前景区域。
  • 增加1,使背景标记为1,前景标记为2,3,4,……

7.应用分水岭算法:

  • 将未标记的未知区域标记为0。
  • 应用分水岭算法进行图像分割,标记边缘区域为-1。

显示结果:

  • 使用Matplotlib显示原始图像、梯度图、形态学处理结果和分水岭标记结果。

通过以上步骤,可以实现对图像的分水岭分割。该方法在处理复杂形状和具有噪声的图像时表现较好。
另外一个分水岭分割代码:


import cv2
import numpy as np
from matplotlib import pyplot as plt#获取背景 
# 1. 通过二值法得到黑白图片
# 2. 通过形态学获取背景img = cv2.imread('water_coins.jpeg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)ret, thresh =cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)#开运算
kernel = np.ones((3,3), np.int8)
open1 = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations = 2)#膨胀
bg = cv2.dilate(open1, kernel, iterations = 1)#获取前景物体
dist = cv2.distanceTransform(open1, cv2.DIST_L2, 5)ret, fg = cv2.threshold(dist,0.7*dist.max(), 255, cv2.THRESH_BINARY)# plt.imshow(dist, cmap='gray')
# plt.show()
# exit()#获取未知区域
fg = np.uint8(fg)
unknow = cv2.subtract(bg, fg)#创建连通域
ret, marker = cv2.connectedComponents(fg)marker = marker + 1
marker[unknow==255] = 0#进行图像分割
result = cv2.watershed(img, marker)img[result == -1] = [0, 0, 255]cv2.imshow("img", img)
cv2.imshow("unknow", unknow)
cv2.imshow("fg", fg)
cv2.imshow("bg", bg)
cv2.imshow("thresh", thresh)
cv2.waitKey()

下面是图片:
https://i-blog.csdnimg.cn/direct/a804c7e0697a48fe9955ea6de5f584e7.jpeg

6. 基于直方图的方法

基于直方图的方法利用图像的灰度或颜色直方图进行分割,如图像分割中的Mean-Shift算法。
示例代码(直方图均衡化)

import cv2
from matplotlib import pyplot as plt# 读取灰度图像
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)# 应用直方图均衡化
equalized_image = cv2.equalizeHist(image)# 显示结果
plt.subplot(1, 2, 1)
plt.title('Original Image')
plt.imshow(image, cmap='gray')plt.subplot(1, 2, 2)
plt.title('Histogram Equalization')
plt.imshow(equalized_image, cmap='gray')plt.show()

7. 基于pyrMeanShiftFiltering分割

pyrMeanShiftFiltering示例代码

import cv2
import numpy as npimg = cv2.imread('key.png')mean_img = cv2.pyrMeanShiftFiltering(img, 20, 30)imgcanny = cv2.Canny(mean_img, 150, 300)contours, _ = cv2.findContours(imgcanny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)cv2.drawContours(img, contours, -1, (0, 0, 255), 2)cv2.imshow('img', img)
cv2.imshow('mean_img', mean_img)
cv2.imshow('canny', imgcanny)
cv2.waitKey()

7. 基于GrabCut算法进行前景分割

GrabCut示例代码

import cv2
import numpy as npclass App:flag_rect = Falserect=(0, 0, 0, 0)startX = 0startY = 0def onmouse(self, event, x, y, flags, param):if event == cv2.EVENT_LBUTTONDOWN:self.flag_rect = Trueself.startX = xself.startY = yprint("LBUTTIONDOWN")elif event == cv2.EVENT_LBUTTONUP:self.flag_rect = Falsecv2.rectangle(self.img, (self.startX, self.startY),(x, y),(0, 0, 255), 3)self.rect = (min(self.startX, x), min(self.startY, y), abs(self.startX - x), abs(self.startY -y))print("LBUTTIONUP")elif event == cv2.EVENT_MOUSEMOVE:if self.flag_rect == True:self.img = self.img2.copy()cv2.rectangle(self.img, (self.startX, self.startY),(x, y),(255, 0, 0), 3)print("MOUSEMOVE")  print("onmouse")def run(self):print("run...")cv2.namedWindow('input')cv2.setMouseCallback('input', self.onmouse)self.img = cv2.imread('./flower.png')self.img2 = self.img.copy()self.mask = np.zeros(self.img.shape[:2], dtype=np.uint8)self.output = np.zeros(self.img.shape, np.uint8)while(1):cv2.imshow('input', self.img)cv2.imshow('output', self.output)k = cv2.waitKey(100)if k == 27:breakif k == ord('g'):bgdmodel = np.zeros((1, 65), np.float64)fgdmodel = np.zeros((1, 65), np.float64)cv2.grabCut(self.img2, self.mask, self.rect,bgdmodel, fgdmodel,1, cv2.GC_INIT_WITH_RECT)mask2 = np.where((self.mask==1)|(self.mask==3), 255, 0).astype('uint8')self.output = cv2.bitwise_and(self.img2, self.img2, mask=mask2)   App().run()

这段代码允许用户通过鼠标在图像上绘制矩形框,并通过GrabCut算法进行前景分割。在运行过程中,用户可以通过鼠标操作绘制矩形,并通过按下g键触发分割算法。

8.视频背景分割:

视频背景分割有三种方法:

  • cv2.bgsegm.createBackgroundSubtractorMOG()
  • cv2.createBackgroundSubtractorMOG2()
  • cv2.bgsegm.createBackgroundSubtractorGMG()

1.cv2.bgsegm.createBackgroundSubtractorMOG()基于高斯混合模型(Mixture of Gaussians, MOG)的背景减法器。它是OpenCV中的一个较早实现版本。
特点:

  • 使用高斯混合模型来表示背景。
  • 对于每个像素,使用多个高斯分布来建模。
  • 更适合静态背景和较慢的场景变化。
    特点:
    使用高斯混合模型来表示背景。
    对于每个像素,使用多个高斯分布来建模。
    更适合静态背景和较慢的场景变化。

2.cv2.createBackgroundSubtractorMOG2()这个函数创建了MOG2背景减法器,是对MOG的改进版本。它是OpenCV中默认和推荐的背景减法方法。
特点:

  • 改进的高斯混合模型,能够自动调整模型中的高斯分布数量。
  • 更加鲁棒,能够更好地处理光照变化和场景中的噪声。
  • 提供阴影检测功能。

3.cv2.bgsegm.createBackgroundSubtractorGMG()这个函数创建了基于统计渐变的背景减法器(GMG)。
特点:

  • 使用逐像素贝叶斯分段和统计渐变。
  • 需要一定数量的初始帧来建立背景模型。
  • 对于处理动态背景和复杂场景非常有效,但初始化较慢。
import cv2
import numpy as npcap = cv2.VideoCapture('./vtest.avi')
#mog = cv2.bgsegm.createBackgroundSubtractorMOG()
# mog = cv2.createBackgroundSubtractorMOG2()
mog = cv2.bgsegm.createBackgroundSubtractorGMG()while(True):ret, frame = cap.read()fgmask = mog.apply(frame)cv2.imshow('img',fgmask)k = cv2.waitKey(10) if k ==27:breakcap.release()
cv2.destroyAllWindows()

9.图像恢复算法

图像恢复算法用于从损坏或降质的图像中恢复原始图像。常用的方法包括:

  • 区域增长法(Region Growing):基于区域扩展修复缺失部分。
  • 纹理合成法(Texture Synthesis):使用相邻区域的纹理填补缺失部分。
  • 深度学习方法:如基于GAN的图像修复方法。

代码示例

import cv2
import numpy as np
img = cv2.imread('inpaint.png')
mask = cv2.imread('inpaint_mask.png', 0)
dst = cv2.inpaint(img, mask, 5, cv2.INPAINT_TELEA)
cv2.imshow('dst', dst)
cv2.imshow('img', img)
cv2.waitKey()
  • inpaint_mask.png:

在这里插入图片描述

  • inpaint.png:
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1556955.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录--栈与队列--用栈实现队列

队列是先进先出&#xff0c;栈是先进后出。 如图所示&#xff1a; 题目 使用栈实现队列的下列操作&#xff1a; push(x) – 将一个元素放入队列的尾部。 pop() – 从队列首部移除元素。 peek() – 返回队列首部的元素。 empty() – 返回队列是否为空。 示例: MyQueue qu…

draw.io 设置默认字体及添加常用字体

需求描述 draw.io 是一个比较好的开源免费画图软件。但是其添加容器或者文本框时默认的字体是 Helvetica&#xff0c;一般的期刊、会议论文或者学位论文要求的英文字体是 Times New Roman&#xff0c;中文字体是 宋体&#xff0c;所以一般需要在文本字体选项里的下拉列表选择 …

分层解耦-05.IOCDI-DI详解

一.依赖注入的注解 在我们的项目中&#xff0c;EmpService的实现类有两个&#xff0c;分别是EmpServiceA和EmpServiceB。这两个实现类都加上Service注解。我们运行程序&#xff0c;就会报错。 这是因为我们依赖注入的注解Autowired默认是按照类型来寻找bean对象的进行依赖注入…

2-115 基于matlab的瞬态提取变换(TET)时频分析

基于matlab的瞬态提取变换&#xff08;TET&#xff09;时频分析&#xff0c;瞬态提取变换是一种比较新的TFA方法。该方法的分辨率较高&#xff0c;能够较好地提取出故障的瞬态特征&#xff0c;用于故障诊断领域。通过对原始振动信号设置不同信噪比噪声&#xff0c;对该方法的抗…

关于一个模仿qq通信程序

7月份的时候还在学校那个时候想要学习嵌入式Linux&#xff0c;但是还没有买开发板来玩&#xff0c;再学linux系统编程&#xff0c;网络编程&#xff0c;Linux系统的文件IO&#xff0c;于是学完之后想做一个模仿qq的通信程序于是就有了这个“ailun.exe”&#xff0c;因为暑假去打…

【数据结构与算法】线性表

文章目录 一.什么是线性表&#xff1f;二.线性表如何存储&#xff1f;三.线性表的类型 我们知道从应用中抽象出共性的逻辑结构和基本操作就是抽象数据类型&#xff0c;然后实现其存储结构和基本操作。下面我们依然按这个思路来认识线性表 一.什么是线性表&#xff1f; 定义 线性…

TryHackMe 第7天 | Web Fundamentals (二)

继续介绍一些 Web hacking 相关的漏洞。 IDOR IDOR (Insecure direct object reference)&#xff0c;不安全的对象直接引用&#xff0c;这是一种访问控制漏洞。 当 Web 服务器接收到用户提供的输入来检索对象时 (包括文件、数据、文档)&#xff0c;如果对用户输入数据过于信…

【springboot】使用代码生成器快速开发

接上一项目&#xff0c;使用mybatis-plus-generator实现简易代码文件生成 在fast-demo-web模块中的pom.xml中添加mybatis-plus-generator、freemarker和Lombok依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator&…

Python | 由高程计算坡度和坡向

写在前面 之前参加一个比赛&#xff0c;提供了中国的高程数据&#xff0c;可以基于该数据进一步计算坡度和坡向进行相关分析。 对于坡度和坡向&#xff0c;这里分享一个找到的库&#xff0c;可以方便快捷的计算。这个库为&#xff1a;RichDEM&#xff0c;官网地址如下 https…

SAP学习笔记 - 豆知识11 - 如何查询某个字段/DataElement/Domain在哪个表里使用?

大家知道SAP的表有10几万个&#xff08;也有说30多万个的&#xff0c;总之很多就是了&#xff09;&#xff0c;而且不断增多&#xff0c;那么当想知道一个字段在哪个表里使用的时候该怎么办呢&#xff1f; 思路就是SAP的表其实也是存在表里的&#xff1a;&#xff09;&#xf…

【Git】TortoiseGitPlink提示输入密码解决方法

问题 克隆仓库&#xff0c;TortoiseGitPlink提示输入密码 解法 1、打开TortoiseGit 下的puttygen工具 位置&#xff1a;C:\Program Files\TortoiseGit\bin\ 2、点击【Load】按钮&#xff0c;载入 C:\Users\Administrator\.ssh\ 文件夹下的id_rsa文件。 3、点击save private …

qt_c++_xml存这种复杂类型

demo&#xff0c;迅雷链接。或者我主页上传的资源 链接&#xff1a;https://pan.xunlei.com/s/VO8bIvYFfhmcrwF-7wmcPW1SA1?pwdnrp4# 复制这段内容后打开手机迅雷App&#xff0c;查看更方便 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>#include…

请散户股民看过来,密切关注两件大事

明天股市要开市&#xff0c;不仅散户股民期盼节后股市大涨&#xff0c;上面也同样想在节后来上一个“开门红”。 为此&#xff0c;上面没休假&#xff0c;关起门来办了两件大事&#xff0c;这两天发布消息已提前预热了。 两件大事如下&#xff1a; 一是&#xff0c;上交所10…

什么是 JavaScript 的数组空槽

JavaScript 中的数组空槽一直是一个非常有趣且颇具争议的话题。我们可能对它的实际意义、历史以及现今的新版本中对它的处理方式有所疑问。数组空槽的存在最早可以追溯到 JavaScript 的诞生之初&#xff0c;当时的设计决定让它成为了现代 JavaScript 开发中的一种特别的现象。 …

大数据新视界 --大数据大厂之数据血缘追踪与治理:确保数据可追溯性

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

计算机毕业设计hadoop+spark天气预测 天气可视化 天气大数据 空气质量检测 空气质量分析 气象大数据 气象分析 大数据毕业设计 大数据毕设

Hadoop天气预测系统开题报告 一、研究背景与意义 在信息化和大数据时代&#xff0c;天气数据已成为社会生活和经济发展中不可或缺的重要资源。天气预测系统作为现代气象学的重要组成部分&#xff0c;对于农业生产、交通管理、环境保护以及防灾减灾等方面都具有重要意义。然而…

集智书童 | 用于时态动作检测的预测反馈 DETR !

本文来源公众号“集智书童”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;用于时态动作检测的预测反馈 DETR ! 视频中的时间动作检测&#xff08;TAD&#xff09;是现实世界中的一个基本且具有挑战性的任务。得益于 Transformer …

Chrome浏览器调用ActiveX控件--allWebOffice控件

背景 allWebOffice控件能够实现在浏览器窗口中在线操作文档的应用&#xff08;阅读、编辑、保存等&#xff09;&#xff0c;支持编辑文档时保留修改痕迹&#xff0c;支持书签位置内容动态填充&#xff0c;支持公文套红&#xff0c;支持文档保护控制等诸多办公功能&#xff0c;本…

国庆期间的问题,如何在老家访问杭州办公室的网络呢

背景&#xff1a;国庆期间的问题&#xff0c;如何在老家访问杭州办公室的网络呢 实现方案&#xff1a;异地组网 实现语言&#xff1a;Java 环境&#xff1a;三个网络&#xff0c;一台拥有公网IP的服务器、一台杭州本地机房内服务器、你老家所在网络中的一台电脑&#xff08;…

Linux中的网络指令:ping、netstat、watch、pidof、xargs

目录 Ping指令 netstat指令 watch指令 pidof指令 xargs指令 Ping指令 功能&#xff1a;检测两台主机间的网络连通性 语法&#xff1a;ping [选项] 目标主机的IP地址 &#xff08;192.168.1.1&#xff09;或域名&#xff08;google.com&#xff09; 常见选项&#xff1a…