【python计算机视觉编程——8.图像内容分类】

news2024/12/24 21:05:00

python计算机视觉编程——8.图像内容分类

  • 8.图像内容分类
    • 8.1 K邻近分类法(KNN)
      • 8.1.1 一个简单的二维示例
      • 8.1.2 用稠密SIFT作为图像特征
      • 8.1.3 图像分类:手势识别
    • 8.2贝叶斯分类器
      • 用PCA降维
    • 8.3 支持向量机
      • 8.3.2 再论手势识别
    • 8.4 光学字符识别
      • 8.4.2 选取特征
      • 8.4.3 多类支持向量机
      • 8.4.4 提取单元格并识别字符
      • 8.4.5 图像校正

8.图像内容分类

8.1 K邻近分类法(KNN)

import numpy as np
class KnnClassifier(object):
    
    
    def __init__(self,labels,samples):
        """ 使用训练数据初始化分类器 """
        
        self.labels = labels
        self.samples = samples
    
    def classify(self,point,k=3):
        """ 在训练数据上采用k近邻分类,并返回标记 """
        
        # 计算所有训练数据点的距离
        dist = np.array([L2dist(point,s) for s in self.samples])
        
        # 对他们进行排序
        ndx = dist.argsort()
        
        # 用字典存储k近邻
        votes = {}
        for i in range(k):
            label = self.labels[ndx[i]]
            votes.setdefault(label,0)
            votes[label] += 1
            
        return max(votes, key=lambda x: votes.get(x))


def L2dist(p1,p2):
    return np.sqrt( sum( (p1-p2)**2) )

8.1.1 一个简单的二维示例

from numpy.random import randn
import pickle

n=200

class_1=0.6*randn(n,2)
class_2=1.2*randn(n,2)+np.array([5,1])
labels=np.hstack((np.ones(n),-np.ones(n)))

# print(class_1)
with open('points_normal.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*np.pi*randn(n,1)
class_2=np.hstack((r*np.cos(angle),r*np.sin(angle)))
labels=np.hstack((np.ones(n),-np.ones(n)))

with open('points_ring.pkl','wb') as f:
    pickle.dump(class_1,f)
    pickle.dump(class_2,f)
    pickle.dump(labels,f)
with open('points_normal.pkl','rb') as f:
    class_1=pickle.load(f)
    class_2=pickle.load(f)
    labels=pickle.load(f)

model=KnnClassifier(labels,np.vstack((class_1,class_2)))

# with open('points_ring.pkl','rb') as f:
#     class_1=pickle.load(f)
#     class_2=pickle.load(f)
#     labels=pickle.load(f)

# print(model.classify(class_1[0]))
from pylab import *

def plot_2D_boundary(plot_range,points,decisionfcn,labels,values=[0]):
    """    Plot_range is (xmin,xmax,ymin,ymax), points is a list
        of class points, decisionfcn is a funtion to evaluate, 
        labels is a list of labels that decisionfcn returns for each class, 
        values is a list of decision contours to show. """
        
    clist = ['b','r','g','k','m','y'] # colors for the classes
    
    # evaluate on a grid and plot contour of decision function
    x = arange(plot_range[0],plot_range[1],.1)
    y = arange(plot_range[2],plot_range[3],.1)
    xx,yy = meshgrid(x,y)
    xxx,yyy = xx.flatten(),yy.flatten() # lists of x,y in grid
    zz = array(decisionfcn(xxx,yyy)) 
    zz = zz.reshape(xx.shape)
    # plot contour(s) at values
    contour(xx,yy,zz,values) 
        
    # for each class, plot the points with '*' for correct, 'o' for incorrect
    for i in range(len(points)):
        d = decisionfcn(points[i][:,0],points[i][:,1])
        correct_ndx = labels[i]==d
        incorrect_ndx = labels[i]!=d
        plot(points[i][correct_ndx,0],points[i][correct_ndx,1],'*',color=clist[i])
        plot(points[i][incorrect_ndx,0],points[i][incorrect_ndx,1],'o',color=clist[i])
    
    axis('equal')
def classify(x,y,model=model):
    return np.array([model.classify([xx,yy]) for (xx,yy) in zip(x,y)])
plot_2D_boundary([-6,6,-6,6],[class_1,class_2],classify,[1,-1])
show()

在这里插入图片描述

8.1.2 用稠密SIFT作为图像特征

from PIL import Image
import os
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.size
    
    if imagename[-3:]!='pgm':
        im.save('tmp.pgm')
        imagename='tmp.pgm'
    scale=size/3.0
    x,y=meshgrid(range(steps,m,steps),range(steps,n,steps))
    xx,yy=x.flatten(),y.flatten()
    frame=np.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)
def read_features_from_file(filename):
    f=loadtxt(filename)
#     print("Array shape:", f.shape)  # 打印数组的形状以调试
    #因为前四列是兴趣点的坐标,尺度和方向角度,后128列是用整数数值表示的描述子
    return f[:,:4],f[:,4:]
def plot_features(im,locs,circle=False):
    def draw_circle(c,r):
        t=arange(0,1.01,.01)*2*pi
        x=r*cos(t)+c[0]
        y=r*sin(t)+c[1]
        plot(x,y,'b',linewidth=2)
        imshow(im)
    if circle:
        for p in locs:
            draw_circle(p[:2],p[2])
    else:
        plot(locs[:,0],locs[:,1],'ob')
    axis('off')
process_image_dsift('sun.jpg','sun.sift',90,40,True)
l,d=read_features_from_file('sun.sift')

im=np.array(Image.open('sun.jpg'))
plot_features(im,l,True)
show()

在这里插入图片描述

8.1.3 图像分类:手势识别

def get_imlist(path,endIdentifier):
    return [os.path.join(path,f) for f in os.listdir(path) if f.endswith(endIdentifier)]
imlist=get_imlist(r'.\train','.ppm')
imtestlist=get_imlist(r'.\test','.ppm')
for filename in imlist:
    featfile=filename[:-3]+'dsift'
    process_image_dsift(filename,featfile,10,5,resize=(50,50))
for filename in imtestlist:
    featfile=filename[:-3]+'dsift'
    process_image_dsift(filename,featfile,10,5,resize=(50,50))
imlist = [r'./train/C-uniform01.ppm', r'./train/B-uniform01.ppm',
          r'./train/A-uniform01.ppm', r'./train/Five-uniform01.ppm',
          r'./train/Point-uniform01.ppm', r'./train/V-uniform01.ppm']
featlist=[]
for filename in imlist:
    featfile=filename[:-3]+'dsift'
    featlist.append(featfile)
# print(imlist)
# print(featlist)

for index,item in enumerate(imlist):
    dirpath, filename = os.path.split(imlist[index])
    im = array(Image.open(imlist[index]).resize((50, 50)))
    titlename = filename[:-14]
    subplot(2, 3, index + 1)
    
    l,d = read_features_from_file(featlist[index])
    plot_features(im, l, True)
    title(titlename)

在这里插入图片描述

def read_gesture_features_labels(path):
    # create list of all files ending in .dsift
    featlist = [os.path.join(path,f) for f in os.listdir(path) if f.endswith('.dsift')]
    # read the features
    features = []
    for featfile in featlist:
        #  print(index)
        l,d = read_features_from_file(featfile)
        
        features.append(d.flatten())
    features = array(features)
    # create labels
    labels = [featfile.split('/')[-1][0] for featfile in featlist]
    return features,array(labels)
features,labels=read_gesture_features_labels(r'.\train\\')
test_features,test_labels=read_gesture_features_labels(r'.\test\\')

classnames=np.unique(labels)
k=1
knn_classifier=KnnClassifier(labels,features)
res=array([knn_classifier.classify(test_features[i],k) for i in
          range(len(test_labels))])

acc=sum(1.0*(res==test_labels))/len(test_labels)
print('Accuracy:',acc)
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]]]+=1
        
    print('Confusion matrix for')
    print(classnames)
    print(confuse)

8.2贝叶斯分类器

import numpy as np 
import pickle
from pylab import *
class BayesClassifier(object):
    
    def __init__(self):
        """ Initialize classifier with training data. """
        
        self.labels = []    # class labels
        self.mean = []        # class mean
        self.var = []        # class variances
        self.n = 0            # nbr of classes
        
    def train(self,data,labels=None):
        """ Train on data (list of arrays n*dim). 
            Labels are optional, default is 0...n-1. """
        
        if labels==None:
            labels = range(len(data))
        self.labels = labels
        self.n = len(labels)
                
        for c in data:
            self.mean.append(np.mean(c,axis=0))
            self.var.append(np.var(c,axis=0))
        
    def classify(self,points):
        """ Classify the points by computing probabilities 
            for each class and return most probable label. """
        
        # compute probabilities for each class
        est_prob = np.array([gauss(m,v,points) for m,v in zip(self.mean,self.var)])
                
        print('est prob',est_prob.shape,self.labels)
        # get index of highest probability, this gives class label
        ndx = est_prob.argmax(axis=0)
        
        est_labels = np.array([self.labels[n] for n in ndx])
        
        return est_labels, est_prob
def gauss(m,v,x):
    """ Evaluate Gaussian in d-dimensions with independent 
        mean m and variance v at the points in (the rows of) x. 
        http://en.wikipedia.org/wiki/Multivariate_normal_distribution """
    
    if len(x.shape)==1:
        n,d = 1,x.shape[0]
    else:
        n,d = x.shape
            
    # covariance matrix, subtract mean
    S = np.diag(1/v)
    x = x-m
    # product of probabilities
    y = np.exp(-0.5*np.diag(np.dot(x,np.dot(S,x.T))))
    
    # normalize and return
    return y * (2*np.pi)**(-d/2.0) / (np.sqrt(np.prod(v)) + 1e-6)
with open('points_normal.pkl','rb') as f:
    class_1=pickle.load(f)
    class_2=pickle.load(f)
    labels=pickle.load(f)

bc=BayesClassifier()
bc.train([class_1,class_2],[1,-1])
print(bc.classify(class_1[:10])[0])

def classify(x,y,bc=bc):
    points=np.vstack((x,y))
    return bc.classify(points.T)[0]

plot_2D_boundary([-6,6,-6,6],[class_1,class_2],classify,[1,-1])

在这里插入图片描述

用PCA降维

from PIL import Image
from numpy import *


def pca(X):
    """    Principal Component Analysis
        input: X, matrix with training data stored as flattened arrays in rows
        return: projection matrix (with important dimensions first), variance and mean.
    """
    
    # get dimensions
    num_data,dim = X.shape
    
    # center data
    mean_X = X.mean(axis=0)
    X = X - mean_X
    
    if dim>num_data:
        # PCA - compact trick used
        M = dot(X,X.T) # covariance matrix
        e,EV = linalg.eigh(M) # eigenvalues and eigenvectors
        tmp = dot(X.T,EV).T # this is the compact trick
        V = tmp[::-1] # reverse since last eigenvectors are the ones we want
        S = sqrt(e)[::-1] # reverse since eigenvalues are in increasing order
        for i in range(V.shape[1]):
            V[:,i] /= S
    else:
        # PCA - SVD used
        U,S,V = linalg.svd(X)
        V = V[:num_data] # only makes sense to return the first num_data
    
    # return the projection matrix, the variance and the mean
    return V,S,mean_X


def center(X):
    """    Center the square matrix X (subtract col and row means). """
    
    n,m = X.shape
    if n != m:
        raise Exception('Matrix is not square.')
    
    colsum = X.sum(axis=0) / n
    rowsum = X.sum(axis=1) / n
    totalsum = X.sum() / (n**2)
    
    #center
    Y = array([[ X[i,j]-rowsum[i]-colsum[j]+totalsum for i in range(n) ] for j in range(n)])
    
    return Y
V,S,m=pca(features)

V=V[:50]
features=np.array([np.dot(V,f,-m) for f in features])
# test_features=np.array([np.dot(V,f,-m) for f in test_features])

bc=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)

8.3 支持向量机

import pickle
from svmutil import *
with open('points_normal.pkl','rb') as f:
    class_1=pickle.load(f)
    class_2=pickle.load(f)
    labels=pickle.load(f)

class_1=map(list,class_1)
class_2=map(list,class_2)
labels=list(labels)
samples=class_1+class_2

prob=svm_problem(labels,samples)
param=svm_parameter('-t 2')

m=svm_train(prob,param)

res=svm_predict(labels,samples,m)
with open('points_normal_test.pkl','rb') as f:
    class_1=pickle.load(f)
    class_2=pickle.load(f)
    labels=pickle.load(f)

class_1=map(list,class_1)
class_2=map(list,class_2)

def predict(x,y,model=m):
    return array(svm_predict([0]*len(x),zip(x,y),model)[0])

plot_2D_boundary([-6,6,-6,6],[class_1,class_2],classify,[1,-1])
show()

8.3.2 再论手势识别

features=map(list,features)
test_features=map(list,test_features)

transl={}
for i,c in enumerate(classnames):
    transl[c],trans[i]=i,c

prob=svm_problem(convert_labels(labels,transl),features)
param=svm_paramter('-t 2')


m=svm_train(prob,param)

res=svm_predict(covert_labels(labels,transl),features,m)

res=svm_predict(convert_labels(test_labelss,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)

8.4 光学字符识别

8.4.2 选取特征

def compute_feature(im):
    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

8.4.3 多类支持向量机

from svmutil import *
features,labels=load_ocr_data('training/')

test_features,test_labels=load_ocr_data('testing/')

features=map(list,features)
test_features=map(list,test_features)

prod=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)

8.4.4 提取单元格并识别字符

from scipy.ndimage import measurements

def find_sudoku_edges(im,axis=0):
    
    trim=1*(im<128)
    s=trim.sum(axis=axis)
    
    s_labels,s_nbr=measurements.label(s>(0.5*max(s)))
    
    m=measurements.center_of_mass(s,s_labels,range(1,s_nbr+1))
    
    x=[int(x[0]) for x in m]
    
    if lem(x)==4:
        dx=diff(x)
        x=[x[0],x[0]+dx[0]/3,x[0]+2*dx[0]/3,
          x[1],x[1]+dx[1]/3,x[1]+2*dx[1]/3,
          x[2],x[2]+dx[2]/3,x[2]+2*dx[2]/3,x[3]]
        
        if len(x)==10:
            return x
        else:
            raise RuntimeError('Edges not detected')
imname='sudokus/sudoku18.jpg'
vername='sudokus/sudoku18.sud'
im=array(Image.open(imname).convert('L'))

x=find_sudoku_edges(im,axis=0)
y=find_sudoku_edges(im,axis=1)

crops=[]
for col in range(9):
    for row in range(9):
        crop=im[y[col]:y[col+1],x[row]:x[row+1]]
        crops.append(compute_feature(crop))
res=svm_predict(loadtxt(vername),map(list,crops),m)[0]
res_im=array(res).reshape(9,9)

print('Result:')
print(res_im)

8.4.5 图像校正

from scipy import ndimage

imname='sudoku8.jpg'
im=array(Image.open(imname).convert('L'))

figure()
imsshow(im)
gray()
x=ginput(4)

fp=array([array([p[1],p[0],1]) for p in x]).T
tp=array([[0,0,1],[0,1000,1],[1000,1000,1],[1000,0,1]]).T

H=H_from_points(tp,fp)

def warpfcn(x):
    x=array([x[0],x[1],1])
    xt=dot(H,x)
    xt=xt/xt[2]
    return xt[0],xt[1]

im_g=ndimage.geometric_transform(im,warpfcn,(1000,1000))

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

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

相关文章

面试官:你是怎么处理vue项目中的错误的?

一、错误类型 任何一个框架&#xff0c;对于错误的处理都是一种必备的能力 在Vue 中&#xff0c;则是定义了一套对应的错误处理规则给到使用者&#xff0c;且在源代码级别&#xff0c;对部分必要的过程做了一定的错误处理。 主要的错误来源包括&#xff1a; 后端接口错误代…

网络原理之TCP协议(万字详解!!!)

目录 前言 TCP协议段格式 TCP协议相关特性 1.确认应答 2.超时重传 3.连接管理&#xff08;三次握手、四次挥手&#xff09; 三次握手&#xff08;建立TCP连接&#xff09; 四次挥手&#xff08;断开连接&#xff09; 4.滑动窗口 5.流量控制 6.拥塞控制 7.延迟应答…

(入门篇)JavaScript 网页设计案例浅析-简单的交互式图片轮播

网页设计已经成为了每个前端开发者的必备技能,而 JavaScript 作为前端三大基础之一,更是为网页赋予了互动性和动态效果。本篇文章将通过一个简单的 JavaScript 案例,带你了解网页设计中的一些常见技巧和技术原理。今天就说一说一个常见的图片轮播效果。相信大家在各类电商网…

使用vscode上传git远程仓库流程(Gitee)

目录 参考附件 git远程仓库上传流程 1&#xff0c;先将文件夹用VScode打开 2&#xff0c;第一次进入要初始化一下仓库 3&#xff0c;通过这个&#xff08;.gitignore&#xff09;可以把一些不重要的文件不显示 注&#xff1a;&#xff08;.gitignore中&#xff09;可屏蔽…

AI辅助编程里的 Atom Group 的概念和使用

背景 在我们实际的开发当中&#xff0c;一个需求往往会涉及到多个文件修改&#xff0c;而需求也往往有相似性。 举个例子&#xff0c;我经常需要在 auto-coder中需要添加命令行参数&#xff0c;通常是这样的&#xff1a; /coding 添加一个新的命令行参数 --chat_model 默认值为…

基于RAG和知识库的智能问答系统设计与实现

开局一张图&#xff0c;其余全靠编。 自己画的图&#xff0c;内容是由Claude根据图优化帮忙写的。 1. 引言 在当今数字化时代&#xff0c;智能问答系统已成为提升用户体验和提高信息获取效率的重要工具。随着自然语言处理技术的不断进步&#xff0c;特别是大型语言模型&#x…

Sonarqube 和 Sonar-scanner的安装和配置

SonarQube 简介 所谓sonarqube 就是代码质量扫描工具。 官网&#xff1a; https://www.sonarsource.com/sonarqube/ 在个人开发学习中用处不大&#xff0c; 我草&#xff0c; 我的代码质量这么高需要这玩意&#xff1f; 但是在公司项目中&#xff0c; 这个可是必须的&#x…

【高校主办,EI稳定检索】2024年人机交互与虚拟现实国际会议(HCIVR 2024)

会议简介 2024年人机交互与虚拟现实国际会议&#xff08;HCIVR 2024&#xff09;定于2024年11月15-17日在中国杭州召开&#xff0c;会议由浙江工业大学主办。人机交互&#xff0c;虚拟现实技术的发展趋势主要体现在系统将越来越实际化&#xff0c;也越来越贴近人类的感知和需求…

心觉:第一性原理思考和共情能力,怎么用效果更好

Hi&#xff0c;我是心觉&#xff0c;与你一起玩转潜意识、脑波音乐和吸引力法则&#xff0c;轻松掌控自己的人生&#xff01; 挑战每日一省写作163/1000天 我很佩服逻辑能力很强的人 也很佩服共情能力很强的人 他们都很厉害 我自己感觉逻辑能力更强一点&#xff0c;平时喜欢…

strlen函数模拟实现(嵌套函数调用)

目录 1.模拟实现strlen函数代码&#xff08;嵌套函数&#xff09; 2.代码解释 小心&#xff01;VS2022不可直接接触&#xff0c;否则..!没有这个必要&#xff0c;方源一把抓住VS2022&#xff0c;顷刻 炼化&#xff01; 1.模拟实现strlen函数代码&#xff08;嵌套函数&#x…

从零开始写论文:如何借助ChatGPT生成完美摘要?

AIPaperGPT&#xff0c;论文写作神器~ https://www.aipapergpt.com/ 在写论文的过程中&#xff0c;摘要是一个非常重要的部分&#xff0c;它能够帮助读者快速理解论文的核心内容&#xff0c;决定是否进一步阅读全文。但是许多学生在写摘要的时候常常感到困惑&#xff0c;不知…

Oracle 19c数据库:Windows详细安装与配置指南

Oracle 19c的安装和配置是一个相对复杂但系统化的过程&#xff0c;本文演示如何在 Windows 系统下安装 Oracle数据库&#xff0c;安装足够的磁盘空间&#xff08;一般需要5~6个G&#xff0c;所以选剩余空间大的盘&#xff09;。以下是一个详细的步骤指南&#xff0c;包括准备工…

多线程 | CompletableFutureAPI简单介绍

文章目录 1. 案例Future方案CompletableFuture方案 2. CompletableFuture方法一览使用new方法supplyAsync方法runAsync方法为什么仍需要CompletableFuture其他API介绍whenCompletethenApplythenAcceptthenComposethenCombineallOf&anyOfsupplyAsync 3. 注意点4. 总结 本文从…

游戏厅计费系统电玩计时系统软件 佳易王计时定时语音提醒管理系统操作教程

一、前言 游戏厅计费系统电玩计时系统软件 佳易王计时定时语音提醒管理系统操作教程 1、佳易王电玩店ps5计时计费软件&#xff0c;可以设置定时语音提醒。 2、软件为免安装版&#xff0c;解压即可。 二、软件程序部分功能图文说明 1、在设置定时语音提醒的时候&#xff0c;只…

第49课 Scratch入门篇:骇客任务背景特效

骇客任务背景特效 故事背景: 骇客帝国特色背景在黑色中慢慢滚动着! 程序原理: 1 、 角色的设计技巧  2 、克隆体的应用及特效的使用 开始编程 1、使用 黑色的背景: ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/7d74c872f06b4d9fbc88aecee634b074.png#pic_c…

以太坊入门

1. 以太坊简介 Vitalik Buterin 在 2013 年 11 月提出了以太坊的概念&#xff0c;其关键思想是&#xff1a;开发一种图灵完备&#xff08;Turing-Complete) 的语言&#xff0c;以允许开发用于区块链和去中心化应用的任意程序&#xff08;智能合约&#xff09;。该概念与比特比相…

驱动(RK3588S)第七课时:单节点设备树

目录 需求一、设备树的概念1、设备树的后缀名&#xff1a;2、设备树的语法格式3、设备树的属性&#xff08;重要&#xff09;4、设备树格式举例 二、设备树所用函数1、如何在内核层种获取设备树节点&#xff1a;2、从设备树上获取 gpio 口的属性3、获取节点上的属性只针对于字符…

【0324】Postgres内核 Shared Buffer Access Rules (共享缓冲区访问规则)说明

0. 章节内容 1. 共享磁盘缓冲区访问机制 (shared disk buffers) 共享磁盘缓冲区有两套独立的访问控制机制:引用计数(a/k/a pin 计数)和缓冲区内容锁。(实际上,还有第三级访问控制:在访问任何属于某个关系表的页面之前,必须持有该关系表的适当类型的锁。这里不讨论关系…

[Linux Kernel Block Layer第一篇] block layer架构设计

目录 1. single queue架构 2. multi-queue架构&#xff08;blk-mq) 3. 问题 随着SSD快速存储设备的发展&#xff0c;内核社区越发发现&#xff0c;存储的性能瓶颈从硬件存储设备转移到了内核block layer&#xff0c;主要因为当时的内核block layer是single hw queue的架构&…

【C语言】插入排序、希尔排序——动图展示

目录 1. 插入排序1.1 基本概念1.2 实现思路1.3 代码部分 2. 希尔排序2.1 为什么会有希尔排序&#xff1f;2.2 基本概念2.3 实现思想1&#xff09;单组排序2&#xff09;多组排序 2.4 代码部分 3. 总结 1. 插入排序 1.1 基本概念 把待排序的记录逐个插入到一个已经排好序的有序…