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 npclass 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 npclass 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 npclass App:startX = 0startY = 0def onmouse(self, event, x, y, flags, param):# print("onmouse")if event == cv2.EVENT_LBUTTONDOWN:self.startX = xself.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()breakApp().run()

在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as npclass App:startX = 0startY = 0flag_rect = Falsedef onmouse(self, event, x, y, flags, param):# print("onmouse")if event == cv2.EVENT_LBUTTONDOWN:self.flag_rect = Trueself.startX = xself.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()breakApp().run()

在这里插入图片描述

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

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

# -*- coding: utf-8 -*-
import cv2
import numpy as npclass App:startX = 0startY = 0flag_rect = Falserect = (0, 0, 0, 0)def onmouse(self, event, x, y, flags, param):# print("onmouse")if event == cv2.EVENT_LBUTTONDOWN:self.flag_rect = Trueself.startX = xself.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 = Falseself.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()breakif 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 npimg = 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 npcap = 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 npcap = 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 npcv2.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 npstart_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 = Falsecv2.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 npimg = 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()

在这里插入图片描述

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Docker智驾开发环境搭建

文章目录 背景1. 什么是容器?2. 什么是Docker?2.1 Docker架构3. 为什么要使用Docker?3.1 Docker容器虚拟化的好处3.2 Docker在开发和运维中的优势4. Docker容器与传统虚拟化的区别4.1 区别4.2 Docker的优势5. Docker的核心概念6. Docker在嵌入式开发中的应用7. docker实践参…

deque容器结构学习笔记

1.结构图 2.deque对比vector和list deque双端队列,就像是list和vector的结合 vector: 优点:1.可以随机读取 2. 空间利用率高 缺点:1. 除了尾插尾删,其他插入删除效率比较低 2. 扩容效率低 list: 优点&…

好用的png图片打包plist工具,推荐使用pngPackerGUI_V2.0

png图片打包plist工具,手把手教你使用pngPackerGUI_V2.0此软件是在pngpacker_V1.1软件基础之后,开发的界面化操作软件,方便不太懂命令行的小白快捷上手使用。1.下载并解压缩软件,得到如下目录,双击打开 pngPackerGUI.e…

C++STL——string类详解及其模拟实现

CSTL——string类 1. STL简介 STL全称standard template libaray,译为标准模板库 需要注意,STL不是C的标准库,而是C标准库的重要组成部分STL是一个包含众多数据结构和算法的软件框架 下面展示STL的六大组件: 本章,我…

三季度营收持续上涨,高途终于“松了一口气”?

近日,高途发布2023年第三季度财报。财报数据显示,高途实现净收入7.89亿元,同比增长30.2%。 同时,高途还透露了对于“AI教育”的布局。AI的发展无疑会给高途更大的机遇和更多的期待。随着人工智能技术在公司产品和服务各环节的落地…

HTML5+CSS3+JS小实例:九宫格图片鼠标移入移出方向感知特效

实例:九宫格图片鼠标移入移出方向感知特效 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport&…

python树的孩子链存储结构

树的孩子链存储结构是一种树的存储方式&#xff0c;它使用孩子兄弟表示法来表示树的结构。在这种存储结构中&#xff0c;树的每个节点都有一个指向其第一个孩子的指针和一个指向其下一个兄弟的指针。这样&#xff0c;可以通过这些指针来表示树的层次结构和节点之间的关系。 具…

springframe工程导入

配置gradle工程 init.d 目录下新建init.gradle allprojects {repositories {mavenLocal()maven {allowInsecureProtocol trueurl https://maven.aliyun.com/nexus/content/repositories/central/}} } 报错Plugin [id: org.jetbrains.dokka, version: 0.10.1, apply: false] w…

其利天下技术总监冯建武受邀出席“2023年电子工程师大会”并作主题演讲

2023年11月23日&#xff0c;由华秋电子发烧友主办的“2023年电子工程师大会暨第三届社区年度颁奖活动”在深圳新一代产业园成功举行。本次年度颁奖活动邀请了高校教授、企业高管、行业专家、资深电子工程师等共300多人出席。聚焦“电机驱动技术”、“开源硬件”、“OpenHarmony…

ChatGLM2-6B微调过程说明文档

参考文档&#xff1a; ChatGLM2-6B 微调(初体验) - 知乎 环境配置 下载anaconda&#xff0c;版本是Anaconda3-2023.03-0-Linux-x86_64.sh&#xff0c;其对应的python版本是3.10&#xff0c;试过3.7和3.11版本的在运行时都报错。 执行下面的命令安装anaconda sh Anaconda3-202…

Linux文件与路径

Linux文件与路径 1、文件结构 ​ Windows和Linux文件系统区别 ​ 在windows平台下&#xff0c;打开“此电脑”&#xff0c;我们可以看到盘符分区 ​ 每个驱动器都有自己的根目录结构&#xff0c;这样形成了多个树并列的情形 ​ 但是在 Linux 下&#xff0c;我们是看不到这些…

linux系统初始化本地git,创建ssh-key

step1, 在linux系统配置你的git信息 sudo apt install -y git//step1 git config --global user.name your_name // github官网注册的用户名 git config --global user.email your_email //gitub官网注册绑定的邮箱 git config --list //可以查看刚才你的配置内容…

Spring之@Autowired 属性多实现和单实现源码解析

Autowired使用过程中遇到疑问&#xff0c;通过源码解析原因 一、起因1、当person只有一个实现类时&#xff0c;TestController中&#xff0c;Person属性随意取名。2、当有Person两个实现类时&#xff0c;TestController中&#xff0c;属性名称必须和实现类名一致&#xff08;ma…

B 树和 B+树 的区别

文章目录 B 树和 B树 的区别 B 树和 B树 的区别 了解二叉树、AVL 树、B 树的概念 B 树和 B树的应用场景 B 树是一种多路平衡查找树&#xff0c;为了更形象的理解。 二叉树&#xff0c;每个节点支持两个分支的树结构&#xff0c;相比于单向链表&#xff0c;多了一个分支。 …

使用C#和HtmlAgilityPack打造强大的Snapchat视频爬虫

概述 Snapchat作为一款备受欢迎的社交媒体应用&#xff0c;允许用户分享照片和视频。然而&#xff0c;由于其特有的内容自动消失特性&#xff0c;爬虫开发面临一些挑战。本文将详细介绍如何巧妙运用C#和HtmlAgilityPack库&#xff0c;构建一个高效的Snapchat视频爬虫。该爬虫能…

vulfocus apache-cve_2021_41773 漏洞复现

vulfocus apache-cve_2021_41773 漏洞复现 名称: vulfocus/apache-cve_2021_41773 描述: Apache HTTP Server 2.4.49、2.4.50版本对路径规范化所做的更改中存在一个路径穿越漏洞&#xff0c;攻击者可利用该漏洞读取到Web目录外的其他文件&#xff0c;如系统配置文件、网站源码…

tabs切换,当点击tabItem时候,改变选中样式,以及content内容区域

效果图展示&#xff1a; html原生代码&#xff1a; <div><div class"buttons-row nav-select riskType" style"padding: 10px;"><div class"shoucang-title-box flex-start"><div class"shoucang-title-item active&q…

案例034:基于微信小程序的课堂助手系统

文末获取源码 开发语言&#xff1a;PHP 框架&#xff1a;PHP 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序运行软件&#xff1a;微信开…

【Python数据结构与算法】--- 递归算法的应用 ---[乌龟走迷宫] |人工智能|探索扫地机器人工作原理

&#x1f308;个人主页: Aileen_0v0 &#x1f525;系列专栏:PYTHON数据结构与算法学习系列专栏&#x1f4ab;"没有罗马,那就自己创造罗马~" 目录 导言 解决过程 1.建立数据结构 2.探索迷宫: 算法思路 递归调用的“基本结束条件” 3.乌龟走迷宫的实现代码: …

Python大数据考题

Python大数据考题&#xff1a; 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 测开的话&#xff0c;你就得学数据库&#xff0c;sql&#xff0c;oracle&#xff0c;尤其sql要…