opencv笔记(13)—— 停车场车位识别

一、所需数据介绍

car1.h5 是训练后保存的模型

class_directionary 是0,1的分类 

二、图像数据预处理

对输入图片进行过滤:

    def select_rgb_white_yellow(self,image): 
        #过滤掉背景
        lower = np.uint8([120, 120, 120])
        upper = np.uint8([255, 255, 255])
        # lower_red和高于upper_red的部分分别变成0,lower_red~upper_red之间的值变成255,相当于过滤背景
        white_mask = cv2.inRange(image, lower, upper)
        self.cv_show('white_mask',white_mask)
        
        masked = cv2.bitwise_and(image, image, mask = white_mask)
        self.cv_show('masked',masked)
        return masked

转为灰度图:

    def convert_gray_scale(self,image):
        return cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

边缘检测:

    def detect_edges(self,image, low_threshold=50, high_threshold=200):
        return cv2.Canny(image, low_threshold, high_threshold)

获取停车场的轮廓然后定为停车场位置,最后可以对停车场针对性操作 

获取需要停车场的车位区域:

    def select_region(self,image):
        """
                手动选择区域
        """
        # first, define the polygon by vertices
        rows, cols = image.shape[:2]
        pt_1  = [cols*0.05, rows*0.90]
        pt_2 = [cols*0.05, rows*0.70]
        pt_3 = [cols*0.30, rows*0.55]
        pt_4 = [cols*0.6, rows*0.15]
        pt_5 = [cols*0.90, rows*0.15] 
        pt_6 = [cols*0.90, rows*0.90]

        vertices = np.array([[pt_1, pt_2, pt_3, pt_4, pt_5, pt_6]], dtype=np.int32) 
        point_img = image.copy()       
        point_img = cv2.cvtColor(point_img, cv2.COLOR_GRAY2RGB)# 画图最好转成RGB的,为了能化出红色的圈,而不是把原图的色彩重建
        for point in vertices[0]:
            cv2.circle(point_img, (point[0],point[1]), 10, (0,0,255), 4)
        self.cv_show('point_img',point_img)
        
        
        return self.filter_region(image, vertices)

       通过几个点框出区域

       我们选择的点,用红圈画出来 

过滤不需要的:

    def filter_region(self,image, vertices):
        """
                剔除掉不需要的地方
        """
        mask = np.zeros_like(image)
        if len(mask.shape)==2:
            cv2.fillPoly(mask, vertices, 255)
            self.cv_show('mask', mask)    
        return cv2.bitwise_and(image, mask)

过滤后:

roi_images = list(map(park.select_region, edge_images))
    park.show_images(roi_images)


三、车位直线检测

霍夫变换:直线检测 

检测所有的直线

list_of_lines = list(map(park.hough_lines, roi_images))
    def hough_lines(self,image):
        #输入的图像需要是边缘检测后的结果
        #minLineLengh(线的最短长度,比这个短的都被忽略)和MaxLineCap(两条直线之间的最大间隔,小于此值,认为是一条直线)
        #rho距离精度,theta角度精度,threshod超过设定阈值才被检测出线段
        return cv2.HoughLinesP(image, rho=0.1, theta=np.pi/10, threshold=15, minLineLength=9, maxLineGap=4)

       cv2.HoughLinesP 不加 P 就是 cv2.HoughLines 也可以用,就是速度会慢一点,P 就是多了一个采样的操作

过滤出需要的线,并画出来:

line_images = []
    for image, lines in zip(test_images, list_of_lines):
        line_images.append(park.draw_lines(image, lines)) 
    park.show_images(line_images)
   def draw_lines(self,image, lines, color=[255, 0, 0], thickness=2, make_copy=True):
        # 过滤霍夫变换检测到直线
        if make_copy:
            image = np.copy(image) 
        cleaned = []
        for line in lines:
            for x1,y1,x2,y2 in line:
                if abs(y2-y1) <=1 and abs(x2-x1) >=25 and abs(x2-x1) <= 55: # 不要斜线和边界线
                    cleaned.append((x1,y1,x2,y2))
                    cv2.line(image, (x1, y1), (x2, y2), color, thickness) # 画线
        print(" No lines detected: ", len(cleaned)) # 打印线的数量
        return image

四、按列划分区域

画出每个列区域的矩形:

rect_images = []
    rect_coords = []
    for image, lines in zip(test_images, list_of_lines):
        new_image, rects = park.identify_blocks(image, lines) # 返回图片, 矩形框
        rect_images.append(new_image)
        rect_coords.append(rects)
        
    park.show_images(rect_images)
def identify_blocks(self,image, lines, make_copy=True):
    if make_copy:
        new_image = np.copy(image)
    #Step 1: 过滤部分直线
    cleaned = []
    for line in lines:
        for x1,y1,x2,y2 in line:
            if abs(y2-y1) <=1 and abs(x2-x1) >=25 and abs(x2-x1) <= 55:
                cleaned.append((x1,y1,x2,y2))
    
    #Step 2: 对直线按照x1进行排序
    import operator
    list1 = sorted(cleaned, key=operator.itemgetter(0, 1)) # 多级排序,先按0:x1,再按1:y1
    
    #Step 3: 找到多个列,相当于每列是一排车
    clusters = {}
    dIndex = 0
    clus_dist = 10

    for i in range(len(list1) - 1):
        distance = abs(list1[i+1][0] - list1[i][0])
        if distance <= clus_dist:
            if not dIndex in clusters.keys(): clusters[dIndex] = [] # .key()返回字典的键值
                                            # list({'Chinasoft':'China', 'Microsoft':'USA'}.keys())
                                            # ['Chinasoft', 'Microsoft']
            clusters[dIndex].append(list1[i])
            clusters[dIndex].append(list1[i + 1])  # 字典clusters[dIndex]中有两个值
                                                   # {dIndex:[list1[i], list1[i+1]]}
            # 这里 append(list1[i + 1]) 好像会导致重复添加,但是不加的话就添加不到每列的最后一个线

        else: # 下一条线和这一条线的x的距离大于 clusters 的话,就说明不再同一列,在新的一列,dIndex 就+1
            dIndex += 1 # dIndex 就是列的标号
    
    #Step 4: 得到坐标
    rects = {}
    i = 0
    for key in clusters:
        all_list = clusters[key]
        cleaned = list(set(all_list))
        if len(cleaned) > 5: # 大于5个就是一个列
            cleaned = sorted(cleaned, key=lambda tup: tup[1]) # 按y1排序,即第二维元素排列,(x1, y1, x2, y2)
            avg_y1 = cleaned[0][1]
            avg_y2 = cleaned[-1][1]
            avg_x1 = 0
            avg_x2 = 0 # 每一列的第一个和最后一个直线的y坐标,x先=0
            for tup in cleaned:
                avg_x1 += tup[0] # x1
                avg_x2 += tup[2] # x2
                # x可能检测到的有的直线长点,有的短点,所以这里x1,x2取个平均值
            avg_x1 = avg_x1/len(cleaned)
            avg_x2 = avg_x2/len(cleaned)
            rects[i] = (avg_x1, avg_y1, avg_x2, avg_y2) # 矩形坐标
            i += 1
    
    print("Num Parking Lanes: ", len(rects))
    #Step 5: 把列矩形画出来
    buff = 7
    for key in rects:
        tup_topLeft = (int(rects[key][0] - buff), int(rects[key][1]))  # x1 - 7 , y1
        tup_botRight = (int(rects[key][2] + buff), int(rects[key][3])) # x1 + 7 , y2
        cv2.rectangle(new_image, tup_topLeft,tup_botRight,(0,255,0),3)
    return new_image, rects

可以看到右边的图效果好一点,可能后面就用右图了 

五、车位区域划分

delineated = []
    spot_pos = []
    for image, rects in zip(test_images, rect_coords):
        new_image, spot_dict = park.draw_parking(image, rects) # 返回图片,字典{每列的每个的车位坐标:当前车位的序号}
        delineated.append(new_image)
        spot_pos.append(spot_dict)
        
    park.show_images(delineated)
    final_spot_dict = spot_pos[1] # 哪个好保存哪个,上面说右边的好,就是[1]的
    print(len(final_spot_dict))
    def draw_parking(self,image, rects, make_copy = True, color=[255, 0, 0], thickness=2, save = True):
        if make_copy:
            new_image = np.copy(image)
        gap = 15.5     # 指定一个车位的两条直线间的距离
        spot_dict = {} # 字典:一个车位对应一个位置
        tot_spots = 0
        #微调,对12列每一列矩形框进行微调
        adj_y1 = {0: 20, 1:-10, 2:0, 3:-11, 4:28, 5:5, 6:-15, 7:-15, 8:-10, 9:-30, 10:9, 11:-32}
        adj_y2 = {0: 30, 1: 50, 2:15, 3:10, 4:-15, 5:15, 6:15, 7:-20, 8:15, 9:15, 10:0, 11:30}
        
        adj_x1 = {0: -8, 1:-15, 2:-15, 3:-15, 4:-15, 5:-15, 6:-15, 7:-15, 8:-10, 9:-10, 10:-10, 11:0}
        adj_x2 = {0: 0, 1: 15, 2:15, 3:15, 4:15, 5:15, 6:15, 7:15, 8:10, 9:10, 10:10, 11:0}
        for key in rects:
            tup = rects[key] # (x1, y1, x2, y2)
            x1 = int(tup[0] + adj_x1[key])
            x2 = int(tup[2] + adj_x2[key])
            y1 = int(tup[1] + adj_y1[key])
            y2 = int(tup[3] + adj_y2[key])
            cv2.rectangle(new_image, (x1, y1),(x2,y2),(0,255,0),2)
            num_splits = int(abs(y2-y1)//gap)   # 一列可以停多少辆车,就是每一列有多少个车位
            for i in range(0, num_splits+1):
                y = int(y1 + i*gap)
                cv2.line(new_image, (x1, y), (x2, y), color, thickness)
            if key > 0 and key < len(rects) -1 :        
                # 画竖直线,key>0 的列右边两列的中间画竖线
                x = int((x1 + x2)/2)
                cv2.line(new_image, (x, y1), (x, y2), color, thickness)
            # 计算数量
            if key == 0 or key == (len(rects) -1):
                tot_spots += num_splits +1
            else:
                tot_spots += 2*(num_splits +1)
                
            # 字典对应好
            if key == 0 or key == (len(rects) -1):
                for i in range(0, num_splits+1):
                    cur_len = len(spot_dict)
                    y = int(y1 + i*gap)
                    spot_dict[(x1, y, x2, y+gap)] = cur_len +1        
            else:
                for i in range(0, num_splits+1):
                    cur_len = len(spot_dict)
                    y = int(y1 + i*gap)
                    x = int((x1 + x2)/2)
                    spot_dict[(x1, y, x, y+gap)] = cur_len +1
                    spot_dict[(x, y, x2, y+gap)] = cur_len +2   
        
        print("total parking spaces: ", tot_spots, cur_len)
        if save:
            filename = 'with_parking.jpg'
            cv2.imwrite(filename, new_image)
        return new_image, spot_dict

结果保存:

    with open('spot_dict.pickle', 'wb') as handle:
        pickle.dump(final_spot_dict, handle, protocol=pickle.HIGHEST_PROTOCOL) # 结果保存

提取车位上有车和无车的数据,以待导入模型训练:

park.save_images_for_cnn(test_images[0],final_spot_dict)
    def save_images_for_cnn(self,image, spot_dict, folder_name ='cnn_data'):
        for spot in spot_dict.keys():  # 裁剪车位有车和没车的数据,然后准备导入模型
            (x1, y1, x2, y2) = spot
            (x1, y1, x2, y2) = (int(x1), int(y1), int(x2), int(y2))
            #裁剪
            spot_img = image[y1:y2, x1:x2]
            spot_img = cv2.resize(spot_img, (0,0), fx=2.0, fy=2.0)   # 放缩一下
            spot_id = spot_dict[spot]
            
            filename = 'spot' + str(spot_id) +'.jpg'
            print(spot_img.shape, filename, (x1,x2,y1,y2))
            
            cv2.imwrite(os.path.join(folder_name, filename), spot_img)

六、模型构建与训练

train.py

import numpy
import os
from keras import applications
from keras.preprocessing.image import ImageDataGenerator
from keras import optimizers
from keras.models import Sequential, Model
from keras.layers import Dropout, Flatten, Dense, GlobalAveragePooling2D
from keras import backend as k
from keras.callbacks import ModelCheckpoint, LearningRateScheduler, TensorBoard, EarlyStopping
from keras.models import Sequential

from keras.layers.normalization.batch_normalization_v1 import BatchNormalization
# from keras.layers.normalization import BatchNormalization
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.initializers import TruncatedNormal
from keras.layers.core import Activation
from keras.layers.core import Flatten
from keras.layers.core import Dropout
from keras.layers.core import Dense


files_train = 0
files_validation = 0

cwd = os.getcwd()
folder = 'train_data/train'
for sub_folder in os.listdir(folder):
    path, dirs, files = next(os.walk(os.path.join(folder,sub_folder)))
    files_train += len(files)


folder = 'train_data/test'
for sub_folder in os.listdir(folder):
    path, dirs, files = next(os.walk(os.path.join(folder,sub_folder)))
    files_validation += len(files)

print(files_train,files_validation)

img_width, img_height = 48, 48
train_data_dir = "train_data/train"
validation_data_dir = "train_data/test"
nb_train_samples = files_train
nb_validation_samples = files_validation
batch_size = 32
epochs = 15
num_classes = 2

model = applications.VGG16(weights='imagenet', include_top=False, input_shape = (img_width, img_height, 3))


for layer in model.layers[:10]:
    layer.trainable = False


x = model.output
x = Flatten()(x)
predictions = Dense(num_classes, activation="softmax")(x)

# model_final = Model(input = model.input, output = predictions)
model_final = Model(inputs = model.input, outputs = predictions)


model_final.compile(loss = "categorical_crossentropy", 
                    optimizer = optimizers.SGD(lr=0.0001, momentum=0.9), 
                    metrics=["accuracy"]) 


train_datagen = ImageDataGenerator(
rescale = 1./255,
horizontal_flip = True,
fill_mode = "nearest",
zoom_range = 0.1,
width_shift_range = 0.1,
height_shift_range=0.1,
rotation_range=5)

test_datagen = ImageDataGenerator(
rescale = 1./255,
horizontal_flip = True,
fill_mode = "nearest",
zoom_range = 0.1,
width_shift_range = 0.1,
height_shift_range=0.1,
rotation_range=5)

train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size = (img_height, img_width),
batch_size = batch_size,
class_mode = "categorical")

validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size = (img_height, img_width),
class_mode = "categorical")

checkpoint = ModelCheckpoint("car1.h5", monitor='val_acc', verbose=1, save_best_only=True, save_weights_only=False, mode='auto', period=1)
early = EarlyStopping(monitor='val_acc', min_delta=0, patience=10, verbose=1, mode='auto')




# history_object = model_final.fit_generator(
# train_generator,
# samples_per_epoch = nb_train_samples,
# epochs = epochs,
# validation_data = validation_generator,
# nb_val_samples = nb_validation_samples,
# callbacks = [checkpoint, early])

history_object = model_final.fit_generator(
train_generator,
steps_per_epoch = nb_train_samples,
epochs = epochs,
validation_data = validation_generator,
validation_steps = nb_validation_samples,
callbacks = [checkpoint, early])

主函数

if __name__ == '__main__':
    test_images = [plt.imread(path) for path in glob.glob('test_images/*.jpg')]
    weights_path = 'car1.h5'
    video_name = 'parking_video.mp4'
    class_dictionary = {}
    class_dictionary[0] = 'empty'
    class_dictionary[1] = 'occupied'
    park = Parking()
    park.show_images(test_images)
    final_spot_dict = img_process(test_images,park) # 返回字典{每个车位坐标:序号}
    model = keras_model(weights_path)
    img_test(test_images,final_spot_dict,model,class_dictionary)
    video_test(video_name,final_spot_dict,model,class_dictionary)

1. cv2.line()-画线条
它有五个参数:

  img:要划的线所在的图像;
  pt1:直线起点
  pt2:直线终点  (坐标分别为宽、高,opencv中图像的坐标原点在左上角)
 color:直线的颜色
 thickness=1:线条粗细,默认是1.如果一个闭合图形设置为-1,那么整个图形就会被填充。
如:cv2.line(img, (0, 0), (511, 511), (0, 0, 255), 5)

2. cv2.circle()-画圆
和cv2.line()大致相同,第2、3个参数分别代表圆的圆心坐标和半径.

如: cv2.circle(img,(447,63), 63, (0,0,255), -1)

3. cv2.rectangle()-画矩形
和cv2.line()大致相同,第2、3个参数分别代表矩阵的左上顶点和右下顶点.

如:cv2.rectangle(img,(384,0),(510,128),(0,255,0),3)

4. cv2.ellipse()-画椭圆
1.要画的椭圆所在的位置 2.椭圆中心点的坐标 3.长轴和短轴的长度 4.椭圆沿逆时针选择角度5.椭圆沿顺时针方向起始角度和结束角度 6.颜色 7.线条的粗细

如:cv2.ellipse(img,(256,256),(100,50),0,0,180,255,-1)
5. cv2.putText()-添加文字
参数如下: 1. 添加文字所在的图像 2.文字内容 3.坐标 4. 字体 5.大小 6. 颜色 7.粗细

如:cv2.putText(img, 'OpenCV', (10, 500), font, 4, (255, 255, 255), 2)
6. cv2.polylines()-画多边形
参数如下:

img:要在上面画多边形的图像
pts:包含多边形上点的数组
isClosed:标志,决定所绘制的多边形是否闭合。若为 True ,则画若干个闭合多边形;若为 False ,则画一条连接所有点的折线
color:多边形颜色
thickness:多边形线的粗细
lineType:多边形线的类型
shift:坐标精确到小数点后第几位
pts = np.array([[10, 5], [20, 30], [70, 20], [50, 10]], np.int32)
pts = pts.reshape((-1, 1, 2))  
cv.polylines(img,pts=pts,isClosed=True, color=(255, 255, 255), thickness=3)
 

cv2.fillPoly(mask, vertices, 255)

cv2.bitwise_and(image, mask)

cv2.HoughLinesP

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

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

相关文章

09、进程和计划任务管理

9.1 查看和控制进程 程序是保存在外部存储介质(如硬盘)中的可执行机器代码和数据的静态集合&#xff0c;而进程是在 CPU 及内存中处于动态执行状态的计算机程序。在 Linux操作系统中&#xff0c;每个程序启动后可以创建一个或多个进程。例如&#xff0c;提供 Web 服务的 httpd …

计算机网络学习记录 网络层 Day4(下)

计算机网络学习记录 网络层 Day4 &#xff08;下&#xff09; 你好,我是Qiuner. 为记录自己编程学习过程和帮助别人少走弯路而写博客 这是我的 github https://github.com/Qiuner ⭐️ ​ gitee https://gitee.com/Qiuner &#x1f339; 如果本篇文章帮到了你 不妨点个赞吧~ 我…

期权懂题库免费!期权开户测试难吗?多少分算合格通过?

今天带你了解期权懂题库免费&#xff01;期权开户测试难吗&#xff1f;多少分算合格通过&#xff1f;期权开户测试通常要求投资者达到一定的合格分数&#xff0c;以确保他们具备足够的理解和知识来参与期权交易。 期权开户测试难吗&#xff1f; 期权开户测试的难度因人而异&am…

PW1558A规格探秘:为何它是电源系统不可或缺的6A双向保护芯片?

描述 PW1558A 是一款先进的 28V 6A 额定双向负载开关&#xff0c; 提供过载、 短路、 输入电压浪涌、 过大冲击电流和过热保护&#xff0c; 为系统供电。 内置的 24mΩ超低 RDS(ON)电源开关有助于减少正常操作期间的功率损耗。 该设备具有两个输入/输出端口 VBUS1 和 VBUS2&…

LSDFi协议赛道4大稳定币项目,以bitget钱包为例

纵览 LSDfi 生态繁荣的基石&#xff0c;LSD 稳定币赛道全解析 近期有许多建立在流动性质押通证的稳定币借贷协议开始出现在大众眼里&#xff0c;今天文章就要带大家来一一了解这些 LSDfi 协议究竟是如何争夺这块诱人的大饼。 LybraFinanceLSD 它透过抵押stETH/ETH 铸造&#…

二叉树系列题

OJ104&#xff1a;二叉树的最大深度 1.题目 2.注意 这里要用left和right接收递归的结果&#xff0c;如果不接收&#xff0c;直接用递归来比较&#xff0c;会出现效率问题。 3.参考代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* str…

【深入理解计算机系统第3版】补码加法

感觉这部分有点难&#xff0c;所以稍微整理记一下。 抱歉中英混合&#xff0c;来回切换输入法真的很折磨人。 负溢出 正常 正溢出 以4位补码加法为例&#xff0c;理解下表(书中P64) 补码最大值Tmax 2^3 - 1 7, 补码最小值Tmin -2^3 -8 xyz x yz z mod 2^4zU2Tw(z)溢…

[书生·浦语大模型实战营]——Lagent AgentLego 智能体应用搭建实现效果

1.完成 Lagent Web Demo 使用&#xff0c;并在作业中上传截图 使用插件 不使用插件&#xff1a; 2.完成 AgentLego 直接使用部分&#xff0c;并在作业中上传截图 原图 结果 3.完成 AgentLego WebUI 使用&#xff0c;并在作业中上传截图。 4.使用 Lagent 或 AgentLego …

Python数据分析案例46——电力系统异常值监测(自编码器,孤立森林,SVMD)

案例背景 多变量的时间序列的异常值监测一直是方兴未艾的话题&#xff0c;我总能看到不少的同学要做什么时间序列预测&#xff0c;然后做异常值监测&#xff0c;但是很多同学都搞不清楚他们的区别。 这里要简单解释一下&#xff0c;时间序列预测是有监督的模型&#xff0c;而…

使用API有效率地管理Dynadot域名,使用API创建文件夹管理域名

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…

contenteditable实现插入标签的输入框功能(Vue3版)

需求&#xff1a;实现一个简易的函数编辑器 点击参数能够往输入框插入标签点击函数能够往输入框插入文本删除能够把标签整体删除输入的参数能够获取到其携带的信息 插入文本 /*** description 点击函数展示到输入框*/ const getValue ({ item, type }: any) > {// 创建…

计算机网络之crc循环冗余校验、子网划分、rip协议路由转发表、时延计算、香浓定理 奈氏准则、TCP超时重传 RTO

crc循环冗余校验 异或运算 : 相同得0,相异得1 从多项式获取除数 在原数据的末端补0 , 0的个数等于最高次项的阶数 如果最后结果的有效位数较少时&#xff0c;前面应该补0&#xff0c;补到个数与阶位相同 子网划分 子网掩码&#xff1a;用于识别IP地址中的网络号和主机号的…

MySQL数据库整体知识点简述

目录 第一章&#xff1a;数据库系统概述 第二章&#xff1a;信息与数据模型 第3章 关系模型与关系规范化理论 第四章——数据库设计方法 第六-七章——MySQL存储引擎与数据库操作管理 第九章——索引 第10章——视图 第11章——MySQL存储过程与函数 第12章——MySQL 触…

深度解析:ISP代理与住宅代理区别

代理充当用户和互联网之间的中介&#xff0c;提供各种功能以增强安全性、隐私性和可访问性。在众多代理类型中&#xff0c;ISP 和住宅代理脱颖而出&#xff0c;每种代理都具有独特的功能和应用。 了解 ISP 代理 代理ISP&#xff0c;通常称为互联网服务提供商代理&#xff0c;通…

打造高效问答系统:合合信息文档解析工具的应用与实践

官.网地址&#xff1a;合合TextIn - 合合信息旗下OCR云服务产品 LLM&#xff08;大型语言模型&#xff09;的应用落地正快速推动着各行各业工作模式的革新。根据埃森哲在2023年发布的研究报告&#xff0c;预计全行业中有40%的工作时间将得到大语言模型的支持与协助。通过引入A…

23种模式之一— — — —适配器模式的详细介绍与讲解

适配器介绍与讲解 一、概念二、适配器模式结构适配器分类核心思想核心角色模式的UML类图应用场景模式优点模式缺点 实例演示图示代码演示运行结果 一、概念 适配器模式&#xff08;别名&#xff1a;包装器&#xff09; 是一种结构型设计模式 将一个类的接口转换成客户希望的另…

存内计算与扩散模型:下一代视觉AIGC能力提升的关键

目录 前言 视觉AIGC的ChatGPT4.0时代 扩散模型的算力“饥渴症” 存内计算解救算力“饥渴症” 结语 前言 ​ 在这个AI技术日新月异的时代&#xff0c;我们正见证着前所未有的创新与变革。尤其是在视觉内容生成领域&#xff08;AIGC&#xff0c;Artificial Intelligence Generate…

家政预约小程序12用户登录

目录 1 创建全局变量2 创建页面3 搭建页面4 实现登录逻辑总结 在小程序中&#xff0c;登录是一个常见的场景。比如我们在小程序预约或者购买时&#xff0c;通常要求用户先登录后购买。如果使用传统方案&#xff0c;登录这个动作其实最终的目的是为了获取用户的openid。而使用低…

如何理解与学习数学分析——第一部分——数学分析概观

第1 部分&#xff1a;数学分析概观(Studying Analysis) 1. 数学分析之面目(What is Analysis like?) 本章说明了分析中的定义、定理和证明。 它介绍了一些符号&#xff0c;并解释了如何使用数学分析中的这些数学符号和数学词汇、以及应该把它们读成什么。它指出了这种类型的…

【通俗易懂搞算法】一篇文章弄懂Manacher算法

Manacher算法 manacher算法解决的问题回文 最长回文子串最长回文子串解法解法1.0解法2.0Manacher算法回文半径、回文直径回文半径数组之前扩的所有位置中所到达的最右回文右边界(R)取得更远边界的中心点的位置(C)Manacher算法优化情形Manacher算法优化情形总结 manacher算法代码…