图像分割与修复

图像分割的方法

(1)传统的图像分割方法

(2)基于深度学习的图像分割方法

传统的图像分割方法

(1)分水岭法

(2)GrabCut法

(3)MeanShift法

(4)背景扣除

分水岭法

 分水岭法原理 

简单来说,如上图所示。图中有很多的沟壑,当用不同颜色的水灌到沟壑中时,在快灌满时会出现一个边界将两边分开。(每张图片有各种各样的像素,那不同的像素之间就形成沟壑)

分水岭法处理步骤

(1)标记背景

(2)标记前景

(3)标记未知域

(4)进行分割

分水岭法实战

分水岭法API

(1)watershed(img,masker)

(2)masker:前景,背景设置不同的值用于区分他们(如何获取前景,背景,和未知区域这个需要腐蚀膨胀的相关知识)

(3)前景可以通过腐蚀或距离变换得到,背景可以通过膨胀得到,未知区域可以使用背景减去前景

(4)距离变换API:distanceTransform(img,distanceType,maskSize)其中

distanceType:是测从非0值到0的距离  DIST_L1 DIST_L2  L1求绝对值 L2求勾股定理 ; maskSize:就是扫描时kernel的大小 L1用3,L2用5

(7)连通域API:connectedComponents(img,connectivity,……)其中

connectivity:4,8(默认)4代表上下左右四个像素如果是一样的就代表是一个连通域,8在4的基础上加上了4个斜对角

 分水岭代码

import cv2
import numpy as np

# 获取背景
# 1,通过二值法得到黑白图片
# 2,通过心态学获取背景

img = cv2.imread('water_coins.jpeg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# THRESH_BINARY二进制阈值。把亮的处理成白色,暗的处理成黑色,超过100的就变成255,反之变为0。我们使用了_INV那就反过来
ret, thresh = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY_INV)


cv2.imshow('dst', thresh)
cv2.waitKey(0)

 可以得到图片,发现银币中间还是会出现黑色,但是我们不希望有黑色。

#改进前
ret, thresh = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY_INV)

#改进后
# cv2.THRESH_OTSU可以自适应阈值,将100写为0
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

  可以得到图片,发现银币中间没有黑色了,达到我们的目的。

 全部的代码

import cv2
import numpy as np

# 获取背景
# 1,通过二值法得到黑白图片
# 2,通过心态学获取背景(膨胀)
# 3.获取前景物体

img = cv2.imread('water_coins.jpeg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# THRESH_BINARY二进制阈值。把亮的处理成白色,暗的处理成黑色,超过100的就变成255,反之变为0。我们使用了_INV那就反过来
# ret, thresh = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY_INV)
# cv2.THRESH_OTSU可以自适应阈值,将100写为0
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# 开运算(去噪)(真的有用!!!)
kernel = np.ones((3, 3), np.int8)
open = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)

# 膨胀
bg = cv2.dilate(open, kernel, iterations=1)

# 获取前景
dist = cv2.distanceTransform(open, cv2.DIST_L2, 5)
ret, fg = cv2.threshold(dist, 0.7 * dist.max(), 255, cv2.THRESH_BINARY)

# 获取未知区域
fg = np.uint8(fg)
unknow = cv2.subtract(bg, fg)

# 创建连通域
ret, marker = cv2.connectedComponents(fg)

marker = marker + 1  # 将所有背景都设为1 前景不变
marker[unknow == 255] = 0

# 进行图像分割
result = cv2.watershed(img, marker)  # 结果中边沿都是-1表示
img[result == -1] = [0, 0, 255]

cv2.imshow('img', img)
cv2.imshow('bg', bg)
cv2.imshow('fg', fg)
cv2.imshow('unknow', unknow)
cv2.waitKey(0)

 GrabCut法

 GrabCut 原理

(1)用户指定前景区域,剩下的是背景区域

(2)用户可以明确指出某些地方为前景或背景

(3)GrabCut采用分段迭代的方法分析前景物体形成模型树

(4)最后根据权重决定某个像素是前景还是背景

GrabCut 实战

(1)主体结构(定义接口,成员变量)

(2)鼠标事件的处理

(3)调用GrabCut实现前景和背景的分离

GrabCut API

grabCut(img,mask,rect,bgdModel,fgdModel,iterator,mode)

mask:生成的掩码   BGD背景0  FGD前景1  PD_BGD可能是背景2   PR_FGD可能是前景3

rect: 检测区域

bgdModel: np.float64 type zero arrays of size (1,65) 

fgdModel: np.float64 type zero arrays of size (1,65)

mode: GC_INIT_WITH_RECT      GC_INIT_WITH_MASK(第一次使用前一个,第二次使用后面的)

GrabCut实战代码 

(1)主体结构的搭建

import cv2
import numpy as np


class App:
    def onmouse(self, event, x, y, flags, param):  # 对于鼠标事件的监听
        print("onmouse")

    def run(self):  # 主体函数
        print("run……")

        cv2.namedWindow('input')
        cv2.setMouseCallback('input', self.onmouse)

        img = cv2.imread('lena.png')
        cv2.imshow('input', img)
        cv2.waitKey(0)


App().run()

(2)添加鼠标事件

    def onmouse(self, event, x, y, flags, param):  # 对于鼠标事件的监听

        # 主要要实现的三个功能(左键的按下,移动和抬起)
        if (event == cv2.EVENT_LBUTTONDOWN):
            self.flag_ract = True
            self.startX = x
            self.startY = y
            print("LBUTTONDOWN")

        elif (event == cv2.EVENT_LBUTTONUP):
            self.flag_ract = False
            cv2.rectangle(self.img,
                          (self.startX, self.startY),
                          (x, y),
                          (0, 0, 255),
                          3)
            print("LBUTTONUP")

        elif (event == cv2.EVENT_MOUSEMOVE):
            if self.flag_ract == True:
                self.img = self.img2.copy()
                cv2.rectangle(self.img,
                              (self.startX, self.startY),
                              (x, y),
                              (255, 0, 0),
                              3)
                print("MOUSEMOVE")
self.img = cv2.imread('lena.png')
        self.img2 = self.img.copy()

        while (1):
            cv2.imshow('input', self.img)
            k = cv2.waitKey(100)
            if (k == 27):
                break

(3) 调用GrabCut实现前景和背景的分离(总)

import cv2
import numpy as np


class App:
    flag_ract = False
    startX = 0
    startY = 0
    rect = (0, 0, 0, 0)

    def onmouse(self, event, x, y, flags, param):  # 对于鼠标事件的监听

        # 主要要实现的三个功能(左键的按下,移动和抬起)
        if (event == cv2.EVENT_LBUTTONDOWN):
            self.flag_ract = True
            self.startX = x
            self.startY = y
            print("LBUTTONDOWN")

        elif (event == cv2.EVENT_LBUTTONUP):
            self.flag_ract = False
            cv2.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("LBUTTONUP")

        elif (event == cv2.EVENT_MOUSEMOVE):
            if self.flag_ract == 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('lena.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):
                break

            # 进行分离
            if 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)

            # 分离后需要把截取的全景取出来
            # 原始图像与上一个掩码  掩码需要的是最大值ff
            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()

MeanShift法

 MeanShift 图像分割原理

(1)该方法并不是用于图像分割的,而是在彩色层面的平滑滤波

(2)会中和和色彩分布相近的颜色,平滑色彩细节,侵蚀掉面积较小的颜色区域

(3)以图像上让任意一点p为圆心,半径为sp,色彩幅值为sr进行不断的迭代

MeanShift 图像分割实战

MeanShift 的API

pyrMeanShiftFiltering(img,sp,sr,maxlevel=1,termcrit=TermCriteria……)

sp:半径

sr:色彩幅值

MeanShift 的实战

import cv2
import numpy as np

img = cv2.imread('flower.png')
mean_img = cv2.pyrMeanShiftFiltering(img, sp=20, sr=30)

canny_img = cv2.Canny(mean_img, 150, 300)

contours, hierarchy = cv2.findContours(canny_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (255, 0, 0), 2)

cv2.imshow('img', img)
cv2.imshow('mean_img', mean_img)
cv2.imshow('canny_img', canny_img)
cv2.waitKey(0)

视频前后背景分离

 视频背景扣除原理

(1)视频是有一组连续的帧组成的

(2)帧与帧之间关系密切(GOP)

(3)在GOP中,背景几乎是不变的

MOG去背景

MOG去背景的API

createBacgroundSubtractorMOG( history(默认值200),nmixtures(高斯范围值,默认5),backgroundRatio(背景比率,默认为0.7),noiseSigma(默认0,自动降噪)

MOG去背景的实战代码

import cv2
import numpy as np

cap = cv2.VideoCapture('vtest.avi')
mog = cv2.bgsegm.createBackgroundSubtractorMOG()

while (True):
    ret, frame = cap.read()
    fgmask = mog.apply(frame)

    cv2.imshow('img', fgmask)

    k = cv2.waitKey(30)
    if k == 27:
        break

cap.release()
cv2.destroyAllWindows()

MOG2去背景 

MOG2去背景优缺点

优点:同MOG类似,不过对亮度产生的阴影有更好的识别

缺点:前后景分离时会产生很多噪点

MOG2去背景API

createBacgroundSubtractorMOG2( history(默认值500),……detecShadow(是否检测阴影,True))

MOG2去背景实战代码

import cv2
import numpy as np

cap = cv2.VideoCapture('vtest.avi')
# 好处,可以计算出阴影部分
# 缺点,会产生很多噪点
mog = cv2.createBackgroundSubtractorMOG2()

while (True):
    ret, frame = cap.read()
    fgmask = mog.apply(frame)

    cv2.imshow('img', fgmask)

    k = cv2.waitKey(30)
    if k == 27:
        break

cap.release()
cv2.destroyAllWindows()

GMG去背景

GMG去背景优缺点

优点:静态背景图像估计和每个像素的贝叶斯分割抗噪性更强

缺点:默认值帧数很大,需要等待较长时间

MOG2去背景API

createBacgroundSubtractorGMG(initializaFranmes(初始帧数 120))

MOG2去背景实战代码

import cv2
import numpy as np

cap = cv2.VideoCapture('vtest.avi')
# 好处,可以算出阴影部分,同时减少噪点
# 缺点,如果采用默认值,开始很长时间没有任何显示
# 解决方法,调整初始参考帧数量
mog = cv2.bgsegm.createBackgroundSubtractorGMG(10)  # 这个就是参考帧数量

while (True):
    ret, frame = cap.read()
    fgmask = mog.apply(frame)

    cv2.imshow('img', fgmask)

    k = cv2.waitKey(30)
    if k == 27:
        break

cap.release()
cv2.destroyAllWindows()

图像修复实战

 

图像修复相关原理

图像修复API

inpaint(img,mask,inpaintRadius,flags)

img:原始图像

mask:与原始图像大小相同的黑底白色的残缺位置的图片(可以自己制作出来)

inpaintRadius:每个破损的点会画一个半径,根据半径内的值计算出破损区域的值并填入

flags:INPAINT_NS , INPAINT_TELEA

图像修复实战代码

import cv2
import numpy as np

img = cv2.imread('inpaint.png')
mask = cv2.imread('inpaint_mask.png', 0)  # 0 使其变成8位

dst = cv2.inpaint(img, mask, 5, cv2.INPAINT_TELEA)

cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey(0)

原图处理后的图

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于SpringBoot的校园电商物流云平台 JAVA简易版

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 商品数据模块2.3 快递公司模块2.4 物流订单模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 商品表3.2.2 快递公司表3.2.3 物流订单表 四、系统展示五、核心代码5.1 查询商品5.2 查询快递公司5.3 查…

[Unity错误解决]There are 2 audio listeners in the scene.

There are 2 audio listeners in the scene. Please ensure there is always exactly one audio listener in the scene. 从组件中找出包含 Audio Listener 的,只激活一个,其他的关掉

POI2012 PRE-Prefixuffix

P3546 [POI2012] PRE-Prefixuffix 题目大意 对于两个字符串 S 1 , S 2 S_1,S_2 S1​,S2​,如果将 S 1 S_1 S1​的一个后缀移动到开头后这个字符串变成了 S 2 S_2 S2​,则称 S 1 , S 2 S_1,S_2 S1​,S2​循环同构。 给定一个长度为 n n n的字符串 S S …

Android Studio打包有哪些优势

大家好,现在移动应用程序的快速发展,开发者需要一个强大又可靠的开发环境来创建和打包高质量的 Android 应用程序。Android Studio 是一款由 Google 官方开发的 Android 应用程序开发环境,提供了许多的优势和便利,那究竟都有哪些优…

【Eachrts】水滴图

引入依赖 npm安装echarts、echarts-liquidfill插件 "echarts": "^5.4.2", "echarts-liquidfill": "^3.1.0",引入插件 import * as echarts from echarts; import echarts-liquidfill;示例 <template><div class"Liqu…

软件设计模式:六大设计原则

文章目录 前言一、开闭原则二、里氏替换原则三、依赖倒转原则四、接口隔离五、迪米特法则六、合成复用原则总结 前言 在软件开发中&#xff0c;为了提高软件系统的可维护性和可复用性&#xff0c;增加软件的可扩展性和灵活性&#xff0c;程序员要尽量根据6条原则来开发程序&am…

Docker 文件和卷 权限拒绝

一 创作背景 再复制Docker影像文件或访问Docker容器内已安装卷上的文件时我们常常会遇到&#xff1a;“权限被拒绝”的错误&#xff0c;在此&#xff0c;您将了解到为什么会出现“权限被拒绝”的错误以及如何解决这个问题。 二 目的 在深入探讨 Docker 容器中的 Permission De…

Java8新特性 Stream

首先创建一个用户的实体类&#xff0c;包括姓名、年龄、性别、地址、赏金 几个属性 Data public class User {//姓名private String name;//年龄private Integer age;//性别private Integer sex;//地址private String address;//赏金private BigDecimal money;public User(St…

2023一整年BurpSuit都更新了什么?

2023一整年BurpSuit都更新了什么&#xff1f; 2023.5之前除了引入了montoya的外&#xff0c;其他基本都属于优化&#xff0c;不统计了。 历史版本地址&#xff1a;https://portswigger.net/burp/releases/archive?y2023 2023.5 Organizer Notes Live crawl paths view 2023.6 …

如何使用Docker搭建青龙面板并结合内网穿透工具发布至公网可访问

文章目录 一、前期准备本教程环境为&#xff1a;Centos7&#xff0c;可以跑Docker的系统都可以使用。本教程使用Docker部署青龙&#xff0c;如何安装Docker详见&#xff1a; 二、安装青龙面板三、映射本地部署的青龙面板至公网四、使用固定公网地址访问本地部署的青龙面板 正文…

ansible变量的使用

本章主要介绍playbook中的变量 自定义变量使用变量文件字典变量列表变量facts变量内置变量变量的过滤器 为了能够写出更实用的playbook&#xff0c;需要在playbook中使用变量。下面来讲解playbook 中常见的变量。本章实验都在/home/lduan/demo2下操作&#xff0c;先把 demo2目…

【高录用快检索】第四届机械设计与仿真国际学术会议(MDS 2024)

【高录用快检索】第四届机械设计与仿真国际学术会议&#xff08;MDS 2024) 2024 4th International Conference on Mechanical Design and Simulation 2024年第四届机械设计与仿真国际学术会议&#xff08;MDS 2024) 将于2024年03月01-03日在中国西安召开。MDS 2024将围绕“…

一篇文章带你了解SpringBoot目录结构

前言 SpringBoot是整合Spring技术栈的一站式框架&#xff0c;是简化Spring技术栈的快速开发脚手架&#xff0c;是一个能够快速构建生产级别的Spring应用的工具。SpringBoot是目前流行的微服务框架&#xff0c;倡导“约定优于配置”&#xff0c;简化Spring项目搭建及开发过程。…

Ubuntu配置GPU资源

0、升级内核为5.15.0-88-generic&#xff1a; 0.1 配置下载源&#xff1a; 在/etc/apt/sources.list.d目录下新建list文件&#xff0c;添加内容&#xff1a; deb http://mirrors.aliyun.com/ubuntu/ focal-updates amin restricted0.2 下载 sudo apt-get install linux-imag…

中小型教育网络安全解决方案

热门IT技术视频教程&#xff1a;https://xmws-it.blog.csdn.net/article/details/134398330?spm1001.2014.3001.5502 一、中小型教育网络的安全现状及挑战 当前&#xff0c;校园网的安全形势非常严峻&#xff0c;大量的垃圾邮件、黑客攻击、病毒蠕虫等困扰着管理者。而且这些作…

java使用面向对象实现图书管理系统

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …

2023年12月21日历史上的今天大事件早读

1375年12月21日 意大利文艺复兴的代表人物薄伽丘逝世 1620年12月21日 英国抵达第一个北美殖民地普利茅斯 1879年12月21日 斯大林出生 1921年12月21日 苏俄电气化计划批准 1928年12月21日 天津劝业场开业 1928年12月21日 中国核化学家王方定出生 1935年12月21日 载客21人的…

飞书+ChatGPT搭建智能AI助手,无公网ip实现公网访问飞书聊天界面

飞书ChatGPT搭建智能AI助手&#xff0c;无公网ip实现公网访问飞书聊天界面 前言环境列表1.飞书设置2.克隆feishu-chatgpt项目3.配置config.yaml文件4.运行feishu-chatgpt项目5.安装cpolar内网穿透6.固定公网地址7.机器人权限配置8.创建版本9.创建测试企业10. 机器人测试 前言 …

qt-C++笔记之app.processEvents()和QApplication::processEvents()的区别

qt-C笔记之app.processEvents()和QApplication::processEvents()的区别 code review! 代码1&#xff1a; QApplication app(argc, argv); app.processEvents(); 代码2: QApplication::processEvents(); 区别 代码1和代码2的区别在于代码1中使用了一个具体的QApplication对…

Java项目的学习记录---12306购票系统的技术架构选型

后端技术架构 选择基于 Spring Boot 3 和 JDK17 进行底层建设 前端技术架构