OpenCV入门11——图像的分割与修复

文章目录

  • 图像分割的基本概念
  • 实战-分水岭法(一)
  • 实战-分水岭法(二)
  • GrabCut基本原理
  • 实战-GrabCut主体程序的实现
  • 实战-GrabCut鼠标事件的处理
  • 实战-调用GrabCut实现图像分割
  • meanshift图像分割
  • 视频前后景分离
  • 其它对视频前后影分离的方法
  • 图像修复

图像分割是计算机视觉中的一个重要领域,通过它我们可以做物体的统计,背景的变换等许多操作,而图像的修复可以说是它的逆运算

图像分割的基本概念

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实战-分水岭法(一)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
未知区域就是背景-前景
在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as np

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

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

ret, thresh = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)

cv2.imshow('thresh', thresh)
if cv2.waitKey(0) & 0xff == 27:
    cv2.destroyAllWindows()

在这里插入图片描述
在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as np

#获取背景 
# 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)

cv2.imshow('thresh', thresh)
if cv2.waitKey(0) & 0xff == 27:
    cv2.destroyAllWindows()

在这里插入图片描述
把硬币膨胀,背景缩小,保证缩小后的背景里没有硬币,并且开运算可以去除背景的噪声

# -*- coding: utf-8 -*-
import cv2
import numpy as np

#获取背景 
# 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)

cv2.imshow('bg', bg)
cv2.imshow('thresh', thresh)
if cv2.waitKey(0) & 0xff == 27:
    cv2.destroyAllWindows()

在这里插入图片描述

实战-分水岭法(二)

在这里插入图片描述
在这里插入图片描述

# -*- coding: utf-8 -*-
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);
plt.imshow(dist, cmap='gray')
plt.show()
exit()

cv2.imshow('bg', bg)
cv2.imshow('thresh', thresh)
if cv2.waitKey(0) & 0xff == 27:
    cv2.destroyAllWindows()

在这里插入图片描述

# -*- coding: utf-8 -*-
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()

cv2.imshow('fg', fg)
cv2.imshow('bg', bg)
cv2.imshow('thresh', thresh)
if cv2.waitKey(0) & 0xff == 27:
    cv2.destroyAllWindows()

在这里插入图片描述

# -*- coding: utf-8 -*-
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)
unknown = cv2.subtract(bg, fg)


cv2.imshow('unknown', unknown)
cv2.imshow('fg', fg)
cv2.imshow('bg', bg)
cv2.imshow('thresh', thresh)
if cv2.waitKey(0) & 0xff == 27:
    cv2.destroyAllWindows()

在这里插入图片描述
计算前景色的连通域

# -*- coding: utf-8 -*-
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)
unknown = cv2.subtract(bg, fg)

# 创建连通域
ret, marker = cv2.connectedComponents(fg)
print(marker)
marker = marker + 1
print(marker)
marker[unknown == 255] = 0

# 进行图像分割
result = cv2.watershed(img, marker)
img[result == -1] = [0, 0, 255]


cv2.imshow('img', img)
cv2.imshow('unknown', unknown)
cv2.imshow('fg', fg)
cv2.imshow('bg', bg)
cv2.imshow('thresh', thresh)
if cv2.waitKey(0) & 0xff == 27:
    cv2.destroyAllWindows()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
详细操作见官方文档
在这里插入图片描述
在这里插入图片描述

GrabCut基本原理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实战-GrabCut主体程序的实现

# -*- coding: utf-8 -*-
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.WINDOW_NORMAL)
        cv2.setMouseCallback('input', self.onmouse)

        img = cv2.imread('./lena.png')
        cv2.imshow('input', img)
        if cv2.waitKey(0) & 0xff == 27:
            cv2.destroyAllWindows()
        
App().run()

在这里插入图片描述

实战-GrabCut鼠标事件的处理

# -*- coding: utf-8 -*-
import cv2
import numpy as np

class App:
    def onmouse(self, event, x, y, flags, param):
        # print("onmouse")
        if event == cv2.EVENT_LBUTTONDOWN:
            print("LBUTTONDOWN")
        elif event == cv2.EVENT_LBUTTONUP:
            print("EVENT_LBUTTONUP")
        elif event == cv2.EVENT_MOUSEMOVE:
            print("EVENT_MOUSEMOVE")
            
    def run(self):
        print("run...")

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

        img = cv2.imread('./lena.png')
        cv2.imshow('input', img)
        if cv2.waitKey(0) & 0xff == 27:
            cv2.destroyAllWindows()
        
App().run()

在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as np

class App:
    startX = 0
    startY = 0

    def onmouse(self, event, x, y, flags, param):
        # print("onmouse")
        if event == cv2.EVENT_LBUTTONDOWN:
            self.startX = x
            self.startY = y
            # print("LBUTTONDOWN")
        elif event == cv2.EVENT_LBUTTONUP:
            cv2.rectangle(self.img, (self.startX, self.startY), (x, y), (0, 255, 0), 2)
            # print("EVENT_LBUTTONUP")
        elif event == cv2.EVENT_MOUSEMOVE:
            print("EVENT_MOUSEMOVE")

    def run(self):
        print("run...")

        cv2.namedWindow('input', cv2.WINDOW_NORMAL)
        cv2.setMouseCallback('input', self.onmouse)
        # 隐式的定义成员变量
        self.img = cv2.imread('./lena.png')
        while True:
            cv2.imshow('input', self.img)
            if cv2.waitKey(100) & 0xff == 27:
                cv2.destroyAllWindows()
                break
        
App().run()

在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as np

class App:
    startX = 0
    startY = 0
    flag_rect = False

    def onmouse(self, event, x, y, flags, param):
        # print("onmouse")
        if event == cv2.EVENT_LBUTTONDOWN:
            self.flag_rect = True
            self.startX = x
            self.startY = y
            # print("LBUTTONDOWN")
        elif event == cv2.EVENT_LBUTTONUP:
            cv2.rectangle(self.img, (self.startX, self.startY), (x, y), (0, 255, 0), 3)
            self.flag_rect = False
            # print("EVENT_LBUTTONUP")
        elif event == cv2.EVENT_MOUSEMOVE:
            if self.flag_rect == True:
                #鼠标每次移动的时候再拷贝一份img2到img用于显示(img会一直刷新,所以之前鼠标移动画的不会影响后面)
                self.img = self.img2.copy()
                cv2.rectangle(self.img, (self.startX, self.startY), (x, y), (255, 255, 0), 3)
            # print("EVENT_MOUSEMOVE")

    def run(self):
        print("run...")

        cv2.namedWindow('input', cv2.WINDOW_NORMAL)
        cv2.setMouseCallback('input', self.onmouse)
        # 隐式的定义成员变量
        self.img = cv2.imread('./lena.png')
        self.img2 = self.img.copy()

        while True:
            cv2.imshow('input', self.img)
            if cv2.waitKey(100) & 0xff == 27:
                cv2.destroyAllWindows()
                break
        
App().run()

在这里插入图片描述

实战-调用GrabCut实现图像分割

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as np

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

    def onmouse(self, event, x, y, flags, param):
        # print("onmouse")
        if event == cv2.EVENT_LBUTTONDOWN:
            self.flag_rect = True
            self.startX = x
            self.startY = y
            # print("LBUTTONDOWN")
        elif event == cv2.EVENT_LBUTTONUP:
            cv2.rectangle(self.img, (self.startX, self.startY), (x, y), (0, 255, 0), 3)
            self.flag_rect = False
            self.rect = (min(self.startX, x), min(self.startY, y), 
                      abs(self.startX - x), abs(self.startY - y))
            # print("EVENT_LBUTTONUP")
        elif event == cv2.EVENT_MOUSEMOVE:
            if self.flag_rect == True:
                #鼠标每次移动的时候再拷贝一份img2到img用于显示(img会一直刷新,所以之前鼠标移动画的不会影响后面)
                self.img = self.img2.copy()
                cv2.rectangle(self.img, (self.startX, self.startY), (x, y), (255, 255, 0), 3)
            # print("EVENT_MOUSEMOVE")

    def run(self):
        print("run...")

        cv2.namedWindow('input', cv2.WINDOW_NORMAL)
        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 True:
            cv2.imshow('input', self.img)
            cv2.imshow('output', self.output)
            k = cv2.waitKey(100)
            if k & 0xff == 27:
                cv2.destroyAllWindows()
                break
            if k & 0xff == 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()

在这里插入图片描述
在这里插入图片描述

meanshift图像分割

基于色彩进行图像分割
在这里插入图片描述
在这里插入图片描述
sp越大模糊程度越大,sp越小模糊程度越小

sr越大,连成一片区域的可能性越大
在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as np

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

cv2.imshow('img', img)
cv2.imshow('mean_img', mean_img)
if cv2.waitKey(0) & 0xff == 27:
    cv2.destroyAllWindows()

在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as np

# cv2.namedWindow('img', cv2.WINDOW_NORMAL)
# cv2.namedWindow('mean_img', cv2.WINDOW_NORMAL)
img = cv2.imread('flower.png')
# img = cv2.imread('E:/pic/picc/IMG_20230610_192709.jpg')
mean_img = cv2.pyrMeanShiftFiltering(img, 20, 30)

imgCanny = cv2.Canny(mean_img, 150, 200)

cv2.imshow('img', img)
cv2.imshow('mean_img', mean_img)
cv2.imshow('imgCanny', imgCanny)
if cv2.waitKey(0) & 0xff == 27:
    cv2.destroyAllWindows()

在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as np

# cv2.namedWindow('img', cv2.WINDOW_NORMAL)
# cv2.namedWindow('mean_img', cv2.WINDOW_NORMAL)
# img = cv2.imread('flower.png')
img = cv2.imread('key.png')
# img = cv2.imread('E:/pic/picc/IMG_20230610_192709.jpg')
mean_img = cv2.pyrMeanShiftFiltering(img, 20, 30)

imgCanny = cv2.Canny(mean_img, 150, 200)

contours, hierarchy = cv2.findContours(imgCanny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

cv2.drawContours(img, contours, -1, (0, 255, 0), 2)

cv2.imshow('img', img)
cv2.imshow('mean_img', mean_img)
cv2.imshow('imgCanny', imgCanny)
if cv2.waitKey(0) & 0xff == 27:
    cv2.destroyAllWindows()

在这里插入图片描述
在这里插入图片描述

视频前后景分离

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as np

cap = cv2.VideoCapture('./MyVideo.wmv')
mog = cv2.bgsegm.createBackgroundSubtractorMOG()

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

    cv2.imshow('img', fgmask)
    k = cv2.waitKey(40)
    if k & 0xff == 27:
        break
cap.release()
cv2.destroyAllWindows()

在这里插入图片描述

其它对视频前后影分离的方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as np

cap = cv2.VideoCapture('./MyVideo.wmv')
# mog = cv2.bgsegm.createBackgroundSubtractorMOG()
# 优点:可以计算出阴影部分
# 缺点:会产生很多噪点
mog = cv2.createBackgroundSubtractorMOG2()

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

    cv2.imshow('img', fgmask)
    k = cv2.waitKey(40)
    if k & 0xff == 27:
        break
cap.release()
cv2.destroyAllWindows()

在这里插入图片描述
在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as np

cv2.namedWindow('img', cv2.WINDOW_NORMAL)
cap = cv2.VideoCapture('./MyVideo.wmv')
# 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(40)
    if k & 0xff == 27:
        break
cap.release()
cv2.destroyAllWindows()

在这里插入图片描述

图像修复

在这里插入图片描述
在这里插入图片描述
生成掩码

# -*- coding: utf-8 -*-
import cv2          
import numpy as np
 
start_point=(0,0) #鼠标开始坐标
lb_down = False #鼠标左键按下的标志,bool型
 
def mouse_event(event,x,y,flags,param):
    global start_point,end_point,lb_down 
    #如果全局变量是int或者str,那么如果想要在函数中对函数变量进行修改,则需要
    #先在函数内,声明其为global,再进行修改,如果是list或者dict则可以直接修改
    
    #左键按下,更新鼠标坐标,启动按下标志
    if event == cv2.EVENT_LBUTTONDOWN:  
        start_point = (x,y)
        lb_down = True
    
    #鼠标移动,绘制线
    elif event == cv2.EVENT_MOUSEMOVE and lb_down: 
        cv2.line(img,start_point,(x,y),(0,0,255),thickness=8)
        cv2.line(mask,start_point,(x,y),(255,255,255),thickness=8)
        #只要鼠标移动,就更新鼠标的坐标  
        start_point = (x,y)      

    #左键释放
    elif event == cv2.EVENT_LBUTTONUP: 
        #鼠标点击后直接释放鼠标的时候也会绘制一个点
        cv2.line(img,start_point,(x,y),(255,255,255),thickness=5)  
        cv2.line(mask,start_point,(x,y),(255,255,255),thickness=5)
        lb_down = False
 
 
cv2.namedWindow('image')   #新建窗口,用来进行鼠标操作       
img = cv2.imread('./inpaint.png')       
mask = np.zeros(img.shape, np.uint8)  #创建一个黑色mask图像
 
cv2.setMouseCallback('image',mouse_event)  #设置鼠标回调
 
while True:
    cv2.imshow('image',img)
    cv2.imshow('mask',mask)
    if cv2.waitKey(1)==ord('q'): #waitKey参数不能写0,写0就需要键盘输入才会继续
        break
cv2.imwrite("./mask.png", mask)
cv2.destroyAllWindows()

在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as np

img = cv2.imread('inpaint.png')
mask = cv2.imread('mask.png', 0)

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

cv2.imshow('dst', dst)
cv2.imshow('img', img)
if cv2.waitKey(0) & 0xff == 27:
    cv2.destroyAllWindows()

在这里插入图片描述

效果很差。。。
之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!

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

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

相关文章

基于springboot实现智慧党建系统项目【项目源码】

基于springboot实现智慧党建系统演示 Java技术 Java是由Sun公司推出的一门跨平台的面向对象的程序设计语言。因为Java 技术具有卓越的通用性、高效性、健壮的安全性和平台移植性的特点,而且Java是开源的,拥有全世界最大的开发者专业社群,所以…

cpp中虚实继承问题

1.一个基类base,被类a虚继承,类a被其他的类继续继承,那么base中的初始化必须由派生类的最后一个完成,其中任意一个都不能代替完成基类,如果在最后一个派生类里不进行这个base的初始化,那么就会调用相应的无…

全面探讨HTTP协议从0.9到3.0版本的发展和特点

前言: 最近的几场面试都问到了http的相关知识点,博主在此结合书籍和网上资料做下总结。本篇文章讲收录到秋招专题,该专栏比较适合刚入坑Java的小白以及准备秋招的大佬阅读。 如果文章有什么需要改进的地方欢迎大佬提出,对大佬有帮…

NetSuite 应用性能管理器(APM)

前段时间,我们发过一个文章谈系统健康检查。 NetSuite ERP系统健康检查-CSDN博客文章浏览阅读119次。“健康检查”本质上是属于信息化持续改善的组成部分。如果说信息化是一个持续不断的过程的话,那么“健康检查”就是持续不断的PDCA中的Check那一环。h…

Python实现定时任务的方案及其比较

目录 一、引言 二、基于time模块的定时任务 三、基于schedule库的定时任务 四、基于APScheduler库的定时任务 五、基于Celery库的定时任务 七、总结与比较 一、引言 在Python中,定时任务指的是在特定的时间间隔或者特定的时间点自动执行某些操作的任务。定时…

C语言--利用选择法对数组中的10个整数按由小到大排序

一.选择法排序介绍🍗 所谓选择法就是先将10个数中最小的数字与arr[0]交换,再将arr[1]-arr[9]中最小的数字与arr[1]进行交换....每一次比较,找出一个未经排序的数中最小的一个。总共比较9轮。 下面以5个数字为例说明选择法的步骤。 二.完整代码…

PubMedBERT:生物医学自然语言处理领域的特定预训练模型

今年大语言模型的快速发展导致像BERT这样的模型都可以称作“小”模型了。Kaggle LLM比赛LLM Science Exam 的第四名就只用了deberta,这可以说是一个非常好的成绩了。所以说在特定的领域或者需求中,大语言模型并不一定就是最优的解决方案,“小…

自动化横行时代,手工测试如何突破重围?测试之路...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 自动化测试是每个…

【C++高阶(五)】哈希思想--哈希表哈希桶

💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:C从入门到精通⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你学习C   🔝🔝 哈希结构 1. 前言2. unordered系列容器3. 哈希概…

01.vue3大事件——项目初始化、技术介绍

后台数据管理系统 - 项目架构设计 在线演示:https://fe-bigevent-web.itheima.net/login 接口文档: https://apifox.com/apidoc/shared-26c67aee-0233-4d23-aab7-08448fdf95ff/api-93850835 接口根路径: http://big-event-vue-api-t.itheima.net 本项…

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《考虑氢储一体化协同的综合能源系统低碳优化》

这个标题涉及到考虑了多个方面的能源系统优化,其中关键的关键词包括"氢储一体化"、"协同"、"综合能源系统"和"低碳优化"。以下是对这些关键词的解读: 氢储一体化: 氢储存: 指的是氢气的存…

网络运维与网络安全 学习笔记2023.11.27

网络运维与网络安全 学习笔记 第二十八天 今日目标 OSPF基本原理、OSPF单区域配置、OSPF多区域配置 特殊区域之Stub、特殊区域之NSSA OSPF基本原理 项目背景 随着企业的发展,网络的规模越来越大,网段的数量越来越多,公司内部的路由器的…

JSP 条件动作标签之choose when otherwise组合标签详解

好 上文JSP 条件动作标签之if标签详解中 我们详细的说了说 if标签 但是 这个if是没有else的 多少对我们的编程习惯没有那么友好 所以 就出现了另外一种语法 由 choose when otherwise组成 和我们java中的switch语句 我们的基本语法就是 外面一个大的choose包裹起来 里面是很多…

VMware上pfsense开源防火墙的下载、安装、简单配置

文章目录 1. pfsense概述1.1. 官方描述1.2. 个人描述 2. pfsense下载2.1. 官网下载 3. pfsense安装3.1. 官网手册3.2. 安装步骤 4. pfsense配置4.1. 默认账号密码4.2. 初始化配置4.3. 切换语言 5. 简单测试5.1. 调整测试网络5.2. 测试结果 6. 虚拟机操作界面讲解7. 最后 1. pfs…

MySQL 高可用架构

MySQL 是实际生产中最常用的数据库,生产环境数据量极为庞大,对性能和安全要求很高,单机的 MySQL 是远远达不到的,所以必须搭建一个主从复制架构,同时可以基于一些工具实现高可用架构,在此基础上&#xff0c…

基于python协同过滤推荐算法的电影推荐与管理系统

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 电影推荐与管理系统是一个基于Python的协同过滤推荐算法的应用,它可以帮助用户根据他们的兴趣和偏好进行…

2016年五一杯数学建模C题二孩政策问题解题全过程文档及程序

2016年五一杯数学建模 C题 二孩政策问题 原题再现 多年来实施的严、紧计划生育政策对控制人口增长起到关键作用。在优生优育政策的指引下,我国人口质量显著提高,但也带来了不利影响,生育率偏低、男女比例失衡、人口老龄化情况严重等问题。2…

Linux 常用基本命令

文章目录 7.1 帮助命令7.1.1 man 获得帮助信息7.1.2 help 获得shell内置命令的帮助信息7.1.3 常用快捷键 7.2 文件目录类7.2.1 pwd 显示当前工作目录的绝对路径7.2.2 ls 列出目录的内容7.2.3 cd 切换目录7.2.4 mkdir 创建一个新的目录7.2.5 rmdir 删除一个空的目录7.2.6 touch …

【JavaEE】多线程 (2) --线程安全

目录 1. 观察线程不安全 2. 线程安全的概念 3. 线程不安全的原因 4. 解决之前的线程不安全问题 5. synchronized 关键字 - 监视器锁 monitor lock 5.1 synchronized 的特性 5.2 synchronized 使⽤⽰例 1. 观察线程不安全 package thread; public class ThreadDemo19 {p…

ICMPv6报文与邻居状态跟踪

ICMPv6报文 ICMPv6(Internet Control Message Protocol for the IPv6)是IPv6的基础协议之一。 在IPv4中,Internet控制报文协议ICMP(Internet Control Message Protocol)向源节点报告关于向目的地传输IP数据包过程中的错误和信息。它为诊断、信息和管理目的定义了一些消息…