Python计算机视觉编程——第8章 图像内容分类

news/2024/9/18 13:40:17/ 标签: python, 计算机视觉, 分类

1 K邻近分类

该算法将要分类的对象与训练集中已知类标记的所有对象进行对比,并由k近邻对指派到哪个类进行投票。该方法的弊端是:与k-means聚类算法一样,需要预先设定k值,k值得选择会影响分类得性能,而且这种方法要求将整个训练集存储起来,当训练集非常大,搜索会较慢。

将定义得类对象添加到knn.py文件中。

python">class KnnClassifier(object):def __init__(self,labels,samples):self.labels = labelsself.samples = samplesdef classify(self,point,k=3):dist = array([L2dist(point,s) for s in self.samples])ndx = dist.argsort()votes = {}for i in range(k):label = self.labels[ndx[i]]votes.setdefault(label,0)votes[label] += 1return max(votes)def L2dist(p1,p2):return sqrt( sum( (p1-p2)**2) )def L1dist(v1,v2):return sum(abs(v1-v2))

使用KNN方法,没有必要存储并将训练数据作为参数来传递。

1.1 一个简单的二维示例

使用如下代码生成4给二维数据集文件,其中points_normal.pkl和points_ring.pkl用于训练,points_normal_test.pkl和points_ring_test.pkl用于测试。

python">from numpy.random import randn
import pickle
from  pylab import *
n=200
class_1 = 0.6 * randn(n,2)
class_2 = 1.2 * randn(n,2) + array([5,1])
labels = hstack((ones(n),-ones(n)))# 用Pickle 模块保存
with open('points_normal_test.pkl', 'wb') as f:pickle.dump(class_1,f)pickle.dump(class_2,f)pickle.dump(labels,f)# 正态分布,并使数据成环绕状分布
class_1 = 0.6 * randn(n,2)
r = 0.8 * randn(n,1) + 5
angle = 2*pi * randn(n,1)
class_2 = hstack((r*cos(angle),r*sin(angle)))
labels = hstack((ones(n),-ones(n)))# 用Pickle 保存
with open('points_ring_test.pkl', 'wb') as f:pickle.dump(class_1,f)pickle.dump(class_2,f)pickle.dump(labels,f)

在这里插入图片描述

使用Pickle模块来创建一个KNN分类器模型

python">from numpy.random import randn
import pickle
from  pylab import *
from PCV.tools import imtools
from PCV.classifiers import knn
from matplotlib import pyplotwith open('points_normal.pkl', 'rb') as f:class_1 = pickle.load(f)class_2 = pickle.load(f)labels = pickle.load(f)
model = knn.KnnClassifier(labels, vstack((class_1, class_2)))with open('points_normal_test.pkl', 'rb') as f:class_1 = pickle.load(f)class_2 = pickle.load(f)labels = pickle.load(f)# 在测试数据集的第一个数据点上进行测试
print (model.classify(class_1[0]))def classify(x,y,model=model):return array([model.classify([xx,yy]) for (xx,yy) in zip(x,y)])# 绘制分类边界
imtools.plot_2D_boundary([-6,6,-6,6],[class_1,class_2],classify,[1,-1])
show()

在这里插入图片描述
不同颜色代表类标记,正确分类的点用星号表示,分类错误的点用圆点标记,曲线是分类器的决策边界。

1.2 用稠密SIFT作为图像特征

对图像进行分类,需要一个特征向量来表示一幅图像,这里用稠密SIFT特征向量。

在整幅图像上用一个规则的网格应用SIFT描述子可以得到稠密SIFT的表示形式。将以下代码添加到dsift.py文件中

python">from PCV.localdescriptors import sift
def process_image_dsift(imagename,resultname,size=20,steps=10,force_orientation=False,resize=None):im = Image.open(imagename).convert('L')if resize!=None:im = im.resize(resize)m,n = im.sizeif imagename[-3:] != 'pgm':#create a pgm fileim.save('tmp.pgm')imagename = 'tmp.pgm'# create frames and save to temporary filescale = size/3.0x,y = meshgrid(range(steps,m,steps),range(steps,n,steps))xx,yy = x.flatten(),y.flatten()frame = array([xx,yy,scale*ones(xx.shape[0]),zeros(xx.shape[0])])savetxt('tmp.frame',frame.T,fmt='%03.3f')if force_orientation:cmmd = str("sift "+imagename+" --output="+resultname+" --read-frames=tmp.frame --orientations")else:cmmd = str("sift "+imagename+" --output="+resultname+" --read-frames=tmp.frame")os.system(cmmd)print('processed', imagename, 'to', resultname)

利用下面的代码计算稠密SIFT描述子,并且可视化它们的位置:

python">from PCV.localdescriptors import dsift
from PCV.localdescriptors import sift
from matplotlib import pyplot
from pylab import *
from PIL import Image
dsift.process_image_dsift('empire.jpg', 'empire.sift', 90, 40, True)
l, d = sift.read_features_from_file('empire.sift')
im = array(Image.open('empire.jpg'))
sift.plot_features(im, l, True)
show()

在这里插入图片描述

1.3 图像分类:手势识别

该应用使用稠密SIFT描述子来表示手势图像,建立一个简单的手势识别系统。
通过下列代码获取每幅图像的稠密SIFT特征:

python">from PCV.localdescriptors import dsift
from PCV.localdescriptors import sift
from matplotlib import pyplot
from pylab import *
from PIL import Image
from PCV.tools.imtools import get_imlistimlist = get_imlist(r'C:\Users\23232\Desktop\data\gesture\fig8-3')
for filename in imlist:featfile = filename[:-3]+'dsift'dsift.process_image_dsift(filename,featfile,10,5,resize=(50,50))

通过下列代码绘制出带有描述子的图像

python">from PCV.localdescriptors import dsift
from PCV.localdescriptors import sift
from matplotlib import pyplot
from pylab import *
from PIL import Image
from PCV.tools.imtools import get_imlist
import os
imlist = ['C:/Users/23232/Desktop/data/gesture/fig8-3/A-uniform01.ppm','C:/Users/23232/Desktop/data/gesture/fig8-3/B-uniform01.ppm','C:/Users/23232/Desktop/data/gesture/fig8-3/c-uniform01.ppm','C:/Users/23232/Desktop/data/gesture/fig8-3/Five-uniform01.ppm','C:/Users/23232/Desktop/data/gesture/fig8-3/Point-uniform01.ppm','C:/Users/23232/Desktop/data/gesture/fig8-3/V-uniform01.ppm']
figure()
for i, im in enumerate(imlist):print(im)dsift.process_image_dsift(im, im[:-3] + 'dsift', 10, 5, True, resize=(50, 50))l, d = sift.read_features_from_file(im[:-3] + 'dsift')dirpath, filename = os.path.split(im)im = array(Image.open(im).resize((50, 50)))titlename = filename[:-14]subplot(2, 3, i + 1)sift.plot_features(im, l, True)title(titlename)
show()

在这里插入图片描述
打印出标记以及相应的混淆矩阵:

python">from PCV.localdescriptors import dsift
import os
from PCV.localdescriptors import sift
from pylab import *
from PCV.classifiers import knndef get_imagelist(path):return [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.ppm')]def read_gesture_features_labels(path):featlist = [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.dsift')]features = []for featfile in featlist:l, d = sift.read_features_from_file(featfile)features.append(d.flatten())features = array(features)labels = [featfile.split('/')[-1][0] for featfile in featlist]return features, array(labels)def print_confusion(res, labels, classnames):n = len(classnames)class_ind = dict([(classnames[i], i) for i in range(n)])confuse = zeros((n, n))for i in range(len(test_labels)):confuse[class_ind[res[i]], class_ind[test_labels[i]]] += 1print('Confusion matrix for')print(classnames)print(confuse)filelist_train = get_imagelist('C:/Users/23232/Desktop/data/gesture/train')
filelist_test = get_imagelist('C:/Users/23232/Desktop/data/gesture/test')
imlist = filelist_train + filelist_testfor filename in imlist:featfile = filename[:-3] + 'dsift'dsift.process_image_dsift(filename, featfile, 10, 5, resize=(50, 50))features, labels = read_gesture_features_labels('C:/Users/23232/Desktop/data/gesture/train/')
test_features, test_labels = read_gesture_features_labels('C:/Users/23232/Desktop/data/gesture/test/')
classnames = unique(labels)k = 1
knn_classifier = knn.KnnClassifier(labels, features)
res = array([knn_classifier.classify(test_features[i], k) for i inrange(len(test_labels))])
acc = sum(1.0 * (res == test_labels)) / len(test_labels)
print('Accuracy:', acc)print_confusion(res, test_labels, classnames)

在这里插入图片描述

2 贝叶斯分类

另一个分类器是贝叶斯分类器,该分类器是基于贝叶斯条件概率定理的概率分类器,假设特征是彼此独立不相关的。该分类器的优势是一旦学习了这个模型,就没有必要存储训练数据了,只需存储模型的参数。
分类器是通过将各个特征的条件概率相乘得到一个类的总概率,然后选取概率最高的那个类构造出来。

将BayesClassifier类添加到文件bayes.py中:

python">class BayesClassifier(object):def __init__(self):""" 使用训练数据初始化分类器 """self.labels = [] # 类标签self.mean = [] # 类均值self.var = [] # 类方差self.n = 0 # 类别数def train(self,data,labels=None):""" 在数据 data(n×dim 的数组列表)上训练,标记labels是可选的,默认为0…n-1 """if labels==None:labels = range(len(data))self.labels = labelsself.n = len(labels)for c in data:self.mean.append(mean(c,axis=0))self.var.append(var(c,axis=0))def classify(self,points):""" 通过计算得出的每一类的概率对数据点进行分类,并返回最可能的标记"""# 计算每一类的概率est_prob = array([gauss(m,v,points) for m,v in zip(self.mean,self.var)])# 获取具有最高概率的索引,该索引会给出类标签ndx = est_prob.argmax(axis=0)est_labels = array([self.labels[n] for n in ndx])return est_labels, est_prob

该模型每一类由两个变量,类均值和协方差。train()方法获取特征数组列表来计算每个特征数组的均值和协方差。

接下来将该贝叶斯分类器用于上一节的二维数据

python">import pickle
from matplotlib import pyplot as plt
from PCV.classifiers import bayes
import numpy as np
from PCV.tools import imtoolswith open(r'points_normal.pkl', 'rb') as f:class_1 = pickle.load(f)class_2 = pickle.load(f)labels = pickle.load(f)
# 训练贝叶斯分类
bc = bayes.BayesClassifier()
bc.train([class_1, class_2], [1, -1])
# 用 Pickle 模块载入测试数据
with open(r'points_normal_test.pkl', 'rb') as f:class_1 = pickle.load(f)class_2 = pickle.load(f)labels = pickle.load(f)
print(bc.classify(class_1[:10])[0])# 绘制这些二维数据点及决策边界
def classify(x, y, bc=bc):points = np.vstack((x, y))return bc.classify(points.T)[0]imtools.plot_2D_boundary([-6, 6, -6, 6], [class_1, class_2], classify, [1, -1])
plt.show()

该例中,决策边界是一个椭圆,类似于二维高斯函数的等值线,正确分类的点用星号表示,错误分类的点用圆点表示。
在这里插入图片描述

用PCA降维
由于稠密SIFT描述子的特征向量十分庞大,在用数据拟合模型前进行降维处理是一个好想法。

python">import pickle
from matplotlib import pyplot as plt
from PCV.classifiers import bayes
import numpy as np
from PCV.tools import imtools
from PCV.tools import pca
from PCV.localdescriptors import dsift
import os
from PCV.localdescriptors import sift
from pylab import *
from PCV.classifiers import knn
def print_confusion(res, labels, classnames):n = len(classnames)class_ind = dict([(classnames[i], i) for i in range(n)])confuse = zeros((n, n))for i in range(len(test_labels)):confuse[class_ind[res[i]], class_ind[test_labels[i]]] += 1print('Confusion matrix for')print(classnames)print(confuse)def read_gesture_features_labels(path):# 对所有以 .dsift 为后缀的文件创建一个列表featlist = [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.dsift')]# 读取特征features = []for featfile in featlist:l, d = sift.read_features_from_file(featfile)features.append(d.flatten())features = np.array(features)# 创建标记labels = [featfile.split('/')[-1][0] for featfile in featlist]return features, np.array(labels)
def get_imagelist(path):return [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.ppm')]filelist_train = get_imagelist('C:/Users/23232/Desktop/data/gesture/train')
filelist_test = get_imagelist('C:/Users/23232/Desktop/data/gesture/test')for filename in filelist_train:featfile = filename[:-3] + 'dsift'dsift.process_image_dsift(filename, featfile, 10, 5, resize=(50, 50))for filename in filelist_test:featfile = filename[:-3] + 'dsift'dsift.process_image_dsift(filename, featfile, 10, 5, resize=(50, 50))
features, labels = read_gesture_features_labels('C:/Users/23232/Desktop/data/gesture/train/')
test_features, test_labels = read_gesture_features_labels('C:/Users/23232/Desktop/data/gesture/test/')
classnames = unique(labels)
V, S, m = pca.pca(features)
# 保持最重要的成分
V = V[:50]
features = array([dot(V, f - m) for f in features])
test_features = array([dot(V, f - m) for f in test_features])# 测试贝叶斯分类
bc = bayes.BayesClassifier()
blist = [features[where(labels == c)[0]] for c in classnames]bc.train(blist, classnames)
res = bc.classify(test_features)[0]acc = sum(1.0*(res==test_labels)) / len(test_labels)
print ('Accuracy:', acc)
print_confusion(res,test_labels,classnames)

在这里插入图片描述
得到准确率约为78.5%,分类效果不如K邻近分类器,分类结果会睡着PCAW维度选取的不同发生变化。

3 支持向量机

SVM是强大的分类器,可以在很多分类问题中给出现有水准很高的分类结果。最简单的SVM在高维空间中寻找到一个最优线性分类面,来将两类数据分开。决策函数为
f ( x ) = w ∗ x − b f(x)=w*x-b f(x)=wxb
其中 w w w是常规的超平面, b b b是偏移量常数。该决策函数的常规解是训练集上某些特征向量的线性组合: w = ∑ i a i y i x i w=\sum_ia_iy_ix_i w=iaiyixi
决策函数可以写为: f ( x ) = ∑ i a i y i x i ∗ x − b f(x)=\sum_ia_iy_ix_i*x-b f(x)=iaiyixixb, i i i是从训练集中选出的部分样本,选择的样本称为支持向量机。

SVM优势是可以使用核函数,核函数能将特征向量映射到另外一个不同维度的空间中。
线性是最简单的情况,即在特征空间中的超平面是线性的, K ( x i , x ) = x i ⋅ x K(x_i,x)=x_i\cdot x K(xi,x)=xix,
多项式用次数为 d d d的多项式对特征进行映射, K ( x i , x ) = ( γ x i ⋅ x + r ) d K( x_i, x) = ( \gamma x_i\cdot x+ r) ^d K(xi,x)=(γxix+r)d, γ > 0 \gamma > 0 γ>0,
径向基函数,通常指数函数是一种极其有效的选择, K ( x i , x ) = e ( ¬ γ ∥ x i − x ∥ 2 ) K( x_i, x) = \mathrm{e} ^{( \neg \gamma \| \mathbf{x} _i- \mathbf{x} \| ^2) } K(xi,x)=e(¬γxix2), γ > 0 ; \gamma > 0; γ>0;
Sigmoid 函数,一个更光滑的超平面替代方案, K ( x i , x ) = tanh ⁡ ( γ x i ⋅ x + r ) K(x_i,x)=\tanh(\gamma x_i\cdot x+r) K(xi,x)=tanh(γxix+r)

3.1 使用LibSVM

LibSVM为Python提供了良好的接口。
使用如下代码载入在前面KNN范例分类中用到的数据点,用径向基函数训练一个SVM分类器:

python">import pickle
from matplotlib import pyplot as plt
from PCV.classifiers import bayes
import numpy as np
from PCV.tools import imtools
from PCV.tools import pca
from PCV.localdescriptors import dsift
import os
from PCV.localdescriptors import sift
from pylab import *
from PCV.classifiers import knn
import pickle
from PCV.libsvm.libsvm.svmutil import *
from PCV.tools import  imtools# 用Pickle 载入二维样本点
with open('points_normal.pkl', 'rb') as f:class_1 = pickle.load(f)class_2 = pickle.load(f)labels = pickle.load(f)# 转换成列表,便于使用libSVM
class_1 = map(list,class_1)
class_2 = map(list,class_2)
labels = list(labels)
samples = list(class_1)+list(class_2) # 连接两个列表
# 创建SVM
prob = svm_problem(labels,samples)
param = svm_parameter('-t 2')# 在数据上训练SVM
m = svm_train(prob,param)#在训练数据上分类效果如何?
res = svm_predict(labels,samples,m)

在这里插入图片描述
显示训练数据中分类的正确率为100%,400个数据点全部分类正确。

3.2 再论手势识别

LibSVM可以自动处理多个类,只需要对数据进行格式化,使得输入和输出匹配LibSVM的要求,下面代码载入训练数据测试数据,并训练一个线性SVM分类器:

python">import pickle
from matplotlib import pyplot as plt
from PCV.classifiers import bayes
import numpy as np
from PCV.tools import imtools
from PCV.tools import pca
from PCV.localdescriptors import dsift
import os
from PCV.localdescriptors import sift
from pylab import *
from PCV.classifiers import knn
from PCV.libsvm.libsvm.svmutil import *
def print_confusion(res, labels, classnames):n = len(classnames)class_ind = dict([(classnames[i], i) for i in range(n)])confuse = zeros((n, n))for i in range(len(test_labels)):confuse[class_ind[res[i]], class_ind[test_labels[i]]] += 1print('Confusion matrix for')print(classnames)print(confuse)def read_gesture_features_labels(path):# 对所有以 .dsift 为后缀的文件创建一个列表featlist = [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.dsift')]# 读取特征features = []for featfile in featlist:l, d = sift.read_features_from_file(featfile)features.append(d.flatten())features = np.array(features)# 创建标记labels = [featfile.split('/')[-1][0] for featfile in featlist]return features, np.array(labels)
def get_imagelist(path):return [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.ppm')]def convert_labels(labels, transl):# 如果 labels 是一个数字数组,则需要将其转换成原始标签if isinstance(labels[0], int):return [transl[i] for i in labels]# 否则,如果 labels 是原始标签,则需要将其转换成数字标签else:return [transl[label] for label in labels]filelist_train = get_imagelist('C:/Users/23232/Desktop/data/gesture/train')
filelist_test = get_imagelist('C:/Users/23232/Desktop/data/gesture/test')for filename in filelist_train:featfile = filename[:-3] + 'dsift'dsift.process_image_dsift(filename, featfile, 10, 5, resize=(50, 50))for filename in filelist_test:featfile = filename[:-3] + 'dsift'dsift.process_image_dsift(filename, featfile, 10, 5, resize=(50, 50))
features, labels = read_gesture_features_labels('C:/Users/23232/Desktop/data/gesture/train/')
test_features, test_labels = read_gesture_features_labels('C:/Users/23232/Desktop/data/gesture/test/')
classnames = unique(labels)
features = list(map(list, features))
test_features = list(map(list, test_features))
# 为标记创建转换函数
transl = {}
for i, c in enumerate(classnames):transl[c], transl[i] = i, c
# 创建 SVM
prob = svm_problem(convert_labels(labels, transl), features)
param = svm_parameter('-t 0')
m = svm_train(prob, param)
# 在训练数据上分类效果如何
res = svm_predict(convert_labels(labels, transl), features, m)
# 测试 SVM
res = svm_predict(convert_labels(test_labels, transl), test_features, m)[0]
res = convert_labels(res, transl)
acc = sum(1.0 * (res == test_labels)) / len(test_labels)
print('Accuracy:', acc)
print_confusion(res, test_labels, classnames)

在这里插入图片描述
分类结果如上图,准确率到达了91.7%

4 光学字符识别

OCR(光学字符识别)是理解手写或机写文本图像的处理过程。一个常见的例子是通过扫描文件来提取文本。

4.1 训练分类

4.2 选取特征

首先确定选取怎样的特征向量来表示每一个单元格李图像。下列代码返回一个拉成一组数组后的灰度值特征向量。

python">def compute_feature(im):""" 对一个 ocr 图像块返回一个特征向量"""# 调整大小,并去除边界norm_im = imresize(im,(30,30))norm_im = norm_im[3:-3,3:-3]return norm_im.flatten()

compute_feature()函数用到了imtools模块中的尺寸调整函数imresize(),以此减少特征向量长度。
使用如下函数来读取训练数据

python">from PCV.tools.imtools import imresize
from PIL import Image
def load_ocr_data(path):imlist = [os.path.join(path,f) for f in os.listdir(path) if f.endswith('.jpg')]#labels = [int(imfile.split('/')[-1][0]) for imfile in imlist]features = []for imname in imlist:im = array(Image.open(imname).convert('L'))features.append(compute_feature(im))return array(features),labels

上述代码将每一个JPEG文件的文件名中的第一个字母提取出来做类标记,并且这
些标记被作为整型数据存储在lables列表里;用上面的函数计算出的特征向量存储
在一个数组里。

4.3 多类支持向量机

得到了训练数据后,接下来学习一个分类器,使用多嘞支持向量机。

python">from PCV.libsvm.libsvm.svmutil import *
from PCV.tools.imtools import imresize
from PIL import Imagedef compute_feature(im):""" 对一个 ocr 图像块返回一个特征向量"""# 调整大小,并去除边界norm_im = imresize(im,(30,30))norm_im = norm_im[3:-3,3:-3]return norm_im.flatten()
def load_ocr_data(path):imlist = [os.path.join(path,f) for f in os.listdir(path) if f.endswith('.jpg')]#labels = [int(imfile.split('/')[-1][0]) for imfile in imlist]features = []for imname in imlist:im = array(Image.open(imname).convert('L'))features.append(compute_feature(im))return array(features),labels
features,labels = load_ocr_data('C:/Users/23232/Desktop/data/sudoku_images/sudoku_images/ocr_data/training/')# 测试数据
test_features,test_labels = load_ocr_data('C:/Users/23232/Desktop/data/sudoku_images/sudoku_images/ocr_data/testing/')
# 训练一个线性SVM分类
features = list(map(list,features))
test_features =list( map(list,test_features))
prob = svm_problem(labels,features)
param = svm_parameter('-t 0')
m = svm_train(prob,param)# 在训练数据上分类效果如何
res = svm_predict(labels,features,m)# 在测试集上表现如何
res = svm_predict(test_labels,test_features,m)

在这里插入图片描述
训练集上的图像都被完美分准确了,测试集上的识别性能也有99%作用。


http://www.ppmy.cn/news/1524795.html

相关文章

AI教你学Python 第1天:Python简介与环境配置

大家好,我是凡人。 为啥要推出这个专栏呢,是因为大模型开发肯定离不开代码,那python可以说是现在流传最广,也非常吃香的语言,所以学Python没错的,所有文章内容全部来自于训练后的大模型生成。 第1天&#…

2024/9/6黑马头条跟学笔记(四)

D4内容介绍 阿里三方安全审核 分布式主键 异步调用 feign 熔断降级 1.自媒体文章自动审核 1.1审核流程 查文章——调接口文本审核——minio下载图片图片审核——审核通过保存文章——发布 草稿1,失败2,人工3,发布9 1.2接口获取 注册阿…

【C++二分查找】2517. 礼盒的最大甜蜜度

本文涉及的基础知识点 C二分查找 贪心(决策包容性) LeetCode 2517. 礼盒的最大甜蜜度 给你一个正整数数组 price ,其中 price[i] 表示第 i 类糖果的价格,另给你一个正整数 k 。 商店组合 k 类 不同 糖果打包成礼盒出售。礼盒的 甜蜜度 是礼…

Leetcode面试经典150题-141.环形链表

题目比较简单,重点是理解思想 解法都在代码里,不懂就留言或者私信 /*** Definition for singly-linked list.* class ListNode {* int val;* ListNode next;* ListNode(int x) {* val x;* next null;* }* }*/ public…

克雷格·费德里吉谈Apple Intelligence保密技术背后的挑战

苹果必须实现克雷格-费德里吉所说的突破,这样 Apple Intelligence公司才能在云中使用大型语言模型,同时还能保护用户隐私,苹果是这样做的。在"It’s Glowtime"活动中,苹果公司谈到了私有云计算作为保护用户隐私的方式。…

高级算法设计与分析 学习笔记5 红黑树

定义: 根节点必黑,红节点孩子必黑,叶子节点(外部节点,null的那种)也是黑,每条路的黑节点数量一致。 首先看各个节点的平衡值,从根节点开始算,哪个最后超过1就是从这里开始…

【Unity新闻】Unity将取消Runtime费用

兜兜转转又回来了,一大早就看到Unity发布新闻,将取消Runtime费用,但同时也将提高各级付费账号的年费。这是新任CEO Matt上任后的价格调整策略。 非常不错的一点是: 当 Unity 6 在今年晚些时候发布时,使用 Unity Pers…

问:有一种Java语法叫注解,一起来扒一扒~

在Java编程语言中,注解(Annotation)和元注解(Meta-Annotation)为开发者提供了丰富的机制来嵌入元数据,从而增强代码的可读性、可维护性,并允许编译器或运行时环境进行特定的处理。 一、注解&am…

大型语言模型:通过代码生成、调试和 CI/CD 集成改变软件开发的游戏规则

借助 AI,软件开发领域正在经历一个突破性阶段,不断集成最先进的大型语言模型,如 GPT-4 和 Claude Opus。这些模型超越了传统开发人员工具的作用,直接帮助开发人员将口头指令转换为跨各种编程语言的可执行代码,从而加快…

深度学习的零碎知识点

显卡内存 什么是显卡内存 简单来说就是,Windows 会在物理显存/「专用 GPU 内存」不够用或只有集成显卡的情况下,将物理内存 RAM 当作 GPU 的虚拟显存/「共享 GPU 内存」来使用。 什么是 Windows「共享 GPU 内存」,它与 VRAM 有什么不同 (s…

【学习笔记】SSL密码套件之哈希

本篇将介绍TLS/SSL密码套件中常用的哈希算法,包括Poly1305、SHA384、SHA256、SHA、MD5 以上的哈希算法将作为 MAC 使用 MAC - Message Authentication Code 为批量数据提供了完整性(Integrity)以及真实性(Authentication&#xf…

yolo学习 (一) 安装yolov8及训练

随便搞个python环境,直接装或者anaconda都行,python版本最低3.8以上 一、安装yolov8 (cpu版本) pip install ultralytics yolov8安装版本比较省事,不过这里默认装的是CPU版本 import torch print(torch.__version_…

前端 + 接口请求实现 vue 动态路由

前端 接口请求实现 vue 动态路由 在 Vue 应用中,通过前端结合后端接口请求来实现动态路由是一种常见且有效的权限控制方案。这种方法允许前端根据用户的角色和权限,动态生成和加载路由,而不是在应用启动时就固定所有的路由配置。 实现原理…

【springboot】整合spring security 和 JWT

目录 1. 整合spring security 1. 导入依赖 2. 配置类 3. 实体类实现UserDetails接口 4. 业务逻辑实现类实现UserDetailsService接口 5. 控制类实现登录功能 6. 测试登录功能 2. 分析源码 1. UsernamePasswordAuthenticationToken 2. A…

windows JOB作业类的处理

windows JOB作业类的处理 windows JOB作业类的处理 文章目录 windows JOB作业类的处理 # windows JOB作业类的处理 /* moduel Job.h Notices: */#pragma once #include <malloc.h> //for _alloca; class CJob { private:HANDLE m_hJob; public:CJob(HANDLE hJob NULL);…

论文翻译:USENIX-2021 Extracting Training Data from Large Language Models

Extracting Training Data from Large Language Models 从大型语言模型中提取训练数据 https://www.usenix.org/system/files/sec21-carlini-extracting.pdf 文章目录 从大型语言模型中提取训练数据摘要1 引言 摘要 现在&#xff0c;发布在私有数据集上训练的大型&#xff…

828华为云征文|基于华为云Flexus云服务器X部署Minio服务

文章目录 ❀前言❀Minio简介❀部署环境准备❀yum环境配置❀安装docker❀获取镜像❀创建挂载目录❀启动容器❀查看容器状态❀安全组开放❀浏览器访问❀总结 ❀前言 大家好&#xff0c;我是早九晚十二。 近期华为云推出了最新的华为云Flexus云服务器X&#xff0c;这款云主机在算…

windows 显示进程地址空间

windows 显示进程地址空间 windows 显示进程地址空间 文章目录 windows 显示进程地址空间显示进程地址空间 显示进程地址空间 /* 3-ProcessInfo.cpp 显示进程地址空间 */#include "..\\CommonFiles\\CmnHdr.h" #include "..\\CommonFiles\\Toolhelp.h"#i…

Debian命令行设置samba共享目录

Samba 是一个用于在 Unix/Linux 系统上实现 SMB/CIFS 网络协议的软件套件,使这些系统能够与 Windows 网络共享文件和打印机。在 Debian 10 上安装和配置 Samba 可以实现 Linux 和 Windows 之间的无缝文件共享。 安装 Samba 1. 更新包列表并安装 Samba: sudo apt update sud…

dplyr、tidyverse和ggplot2初探

dplyr、tidyverse 和 ggplot2 之间有紧密的联系&#xff0c;它们都是 R 语言中用于数据处理和可视化的工具&#xff0c;且都源于 Hadley Wickham 的工作。它们各自有不同的功能&#xff0c;但可以无缝协作&#xff0c;帮助用户完成从数据处理到数据可视化的工作流。以下是它们之…