基于Yolov7图像识别的CF自瞄

提示:本文只做学习和交流使用,本人不推荐使用,还是老老实实靠技术上分吧。

文章目录

前言

一、yolov7环境配置

二、yolov7代码与预训练模型下载

三、采集CF图像数据集

四、CF图像数据集标注

1.Anconda环境使用pip安装labelimg

2、数据集划分

五、yolov7模型训练

六、.pt权重文件转.onnx模型

七、onnx模型推理与鼠标控制

1、使用 mss 模块实时截取屏幕保存到本地,使用 cv2 读取图像。

2、 onnx 模型推理 cv2 读取到的图像

3、计算各个人物中心坐标,并计算其与鼠标的距离判断距离鼠标最近的人物

4、获取鼠标位置并控制鼠标移动到人物中心 

5、onnx模型推理与鼠标控制总代码 

总结


前言

  刚学 yolo 的时候就想着能不能用 yolo 去做一些比较有意思的项目,既可以加深我对 yolo 模型的理解,也能让我彻底提起编程的兴趣。对于本人来说我认为编程最有意思的地方在于我脑袋里经常有很多稀奇古怪的想法,然后我就想去实现它,经历过很多困难之后实现了出来,这种感觉颇具成就感,这跟高中做数学题是一样的想法,我很享受这种成就感。

   这里主要想说一下用 yolov7 的思路:

        1、先用截屏的代码在游戏中获得我们的CF数据集,并进行标注。

        2、标记好的数据使用 yolov7 训练、转成 onnx 模型进行推理。

        3、在打游戏的时候使用截屏的代码将游戏的画面实时存储在本地,名为 Image.jpg,接着下一时刻使用 cv2 读取这张图像,并使用 onnx 模型进行推理识别;

   这篇文章主要是分为:yolov7环境配置、yolov7代码与预训练模型下载、使用mss模块截取CF训练数据图像、labelimg标注CF数据集、yolov7代码训练、.pt 模型转.onnx模型、onnx模型推理识别与控制鼠标等步骤来进行总结。

   本人环境:3060Ti + 8G显卡、1.9.0版本pytorch、3.7.9版本python、Anaconda虚拟环境名为yolov7。

   算法参考大佬:https://blog.csdn.net/weixin_69999177/article/details/125135969


一、yolov7环境配置

yolov7环境配置比较简单不过多赘述,可以参考大佬:YOLOv7(目标检测)入门教程详解---环境安装_yolo安装_螺丝工人的博客-CSDN博客

二、yolov7代码与预训练模型下载

yolov7代码下载网站:https://github.com/WongKinYiu/yolov7

预训练模型使用的是 YOLOv7-X 模型,在上面的网站一并下载。

下载完成之后打开 yolov7 文件夹,在根目录下新建一个名为 weights 的文件夹,这文件夹主要是拿来存放我们的权重文件,把下载好的预训练模型放入该文件夹,并把预训练模型名字改为yolov7x_training.pt 。

用 pycharm 打开文件夹,选择刚刚配置好的环境,打开 detect.py ,修改以下参数默认值:

1、--weights >>> ' weights/yolov7x_training.pt '

2、device >>> ' 0 '

其他参数保持默认,如图 2-1,接着运行 detect.py 即可,运行结果在 runs/detect/exp 文件夹下,若你的运行结果如图 2-2 所示,那么 yolov7 的环境配置就完成了,我们就可以接着走下一步了。

图2-1

图2-2

三、采集CF图像数据集

之前我在网上找了找 CF 数据集但是没找到我就只能自己去游戏里截图了,在游戏中运行下面的代码就可以了,我大概截取了1000张图像,再经过一些数据的清洗、挑选,能用的大概有700张图像左右,不过也够用了。

使用的是 mss 模块中的屏幕截取功能, width 和 height 的值是自己游戏中屏幕分辨率的值,"camera/Image_{0}.jpg" 中的 camera 为当前代码根目录下已经存在的文件夹名,没有则需要自行创建,否则会报错,截取到的CF数据集图像如图3-1所示。

grab_Image().py

import mss.tools
import mss
import cv2
import numpy as np
import time# 定义屏幕宽和高
width = 2560
height = 1440rect = (0, 0, width, height)
m = mss.mss()
mt = mss.tools# 截图保存
def screen_record():img = m.grab(rect)image = np.array(img)cv2.imwrite("camera/Image_{0}.jpg".format(time.strftime("%Y_%m_%d_%H_%M_%S", time.localtime())), image)def main():while True:start = time.time()screen_record()end = time.time()print("time: ", end - start)if __name__ == "__main__":main()
图3-1

四、CF图像数据集标注

1.Anconda环境使用pip安装labelimg

使用以下命令进入自己建的 Anaconda 虚拟环境,并使用 pip 命令安装labelimg

conda activate yolov7

pip install -i https://mirror.baidu.com/pypi/simple labelimg

安装完成之后,在命令行输入 labelimg 打开图像标注软件,如图4-1所示。

图4-1

labelimg图像标注软件的使用我就不说了,很简单,可以参考这篇博客:https://blog.csdn.net/didiaopao/article/details/119808973?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168474650116800192212211%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=168474650116800192212211&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-119808973-null-null.142^v87^insert_down28,239^v2^insert_chatgpt&utm_term=labelimg&spm=1018.2226.3001.4187

导入图像和选择输出位置之后记得选择 YOLO 格式的标签,我这次只标注了全身,若是想要实现锁头,则标注人物的头部,标签名字为:enemy, 标注图像如图4-2所示。

图4-2

2、数据集划分

图像数据集全部标注完成之后,打开保存标签的路径,删除 classes.txt ,使用以下的程序生成以图像名匹配的 txt 文件,这是因为你在标注CF图像数据集的时候有的图像没有人物,就没有标注这张图像,导致没有这张图像的标签文件,这在训练的时候是会报错的,为了防止这些错误,因此我们需要手动生成这些空的标签文件,代码如下,image_path 是图像数据集的路径,result_txt_path 是生成的标签的路径。空的标签生成之后,只需要把我们刚刚标注好的标签复制到这个生成的标签的路径就行了,这 result_txt_path 就是我们训练需要的标签路径。

import osimage_path = "camera"
result_txt_path = "labels"for image in os.listdir(image_path):with open(image.strip(".")[0] + ".txt", "w") as file:file.close()

生成标签路径之后,我们需要在我们的yolov7文件夹的根目录下新建一个datasets文件,里面存放的是我们划分好的数据集;在yolov7根目录下新建一个 cut_dataset.py 文件,我们现在需要把我们的CF数据集按照8:1:1的比例划分为训练集、验证集、测试集,使用以下代码进行划分,

image_original_path 是我们的图像数据集路径,label_original_path 是我们的标签路径,defect1 文件夹下存放的是我们划分好的图像数据和标签,如图4-3所示。

cut_dataset.py

# 将图片和标注数据按比例切分为 训练集和测试集
import shutil
import random
import os# 原始路径
image_original_path =  "C:/Users/Admin/Desktop/test/result_img/"
label_original_path = "C:/Users/Admin/Desktop/test/labels/"cur_path = os.getcwd()# 训练集路径
train_image_path = os.path.join(cur_path, "datasets/defect1/images/train/")
train_label_path = os.path.join(cur_path, "datasets/defect1/labels/train/")# 验证集路径
val_image_path = os.path.join(cur_path, "datasets/defect1/images/val/")
val_label_path = os.path.join(cur_path, "datasets/defect1/labels/val/")# 测试集路径
test_image_path = os.path.join(cur_path, "datasets/defect1/images/test/")
test_label_path = os.path.join(cur_path, "datasets/defect1/labels/test/")# 训练集目录
list_train = os.path.join(cur_path, "datasets/defect1/train.txt")
list_val = os.path.join(cur_path, "datasets/defect1/val.txt")
list_test = os.path.join(cur_path, "datasets/defect1/test.txt")train_percent = 0.8
val_percent = 0.1
test_percent = 0.1def del_file(path):for i in os.listdir(path):file_data = path + "\\" + ios.remove(file_data)def mkdir():if not os.path.exists(train_image_path):os.makedirs(train_image_path)else:del_file(train_image_path)if not os.path.exists(train_label_path):os.makedirs(train_label_path)else:del_file(train_label_path)if not os.path.exists(val_image_path):os.makedirs(val_image_path)else:del_file(val_image_path)if not os.path.exists(val_label_path):os.makedirs(val_label_path)else:del_file(val_label_path)if not os.path.exists(test_image_path):os.makedirs(test_image_path)else:del_file(test_image_path)if not os.path.exists(test_label_path):os.makedirs(test_label_path)else:del_file(test_label_path)def clearfile():if os.path.exists(list_train):os.remove(list_train)if os.path.exists(list_val):os.remove(list_val)if os.path.exists(list_test):os.remove(list_test)def main():mkdir()clearfile()file_train = open(list_train, 'w')file_val = open(list_val, 'w')file_test = open(list_test, 'w')total_txt = os.listdir(label_original_path)# total_img = os.listdir(image_original_path)num_txt = len(total_txt)list_all_txt = range(num_txt)num_train = int(num_txt * train_percent)num_val = int(num_txt * val_percent)num_test = num_txt - num_train - num_valtrain = random.sample(list_all_txt, num_train)# train从list_all_txt取出num_train个元素# 所以list_all_txt列表只剩下了这些元素val_test = [i for i in list_all_txt if not i in train]# 再从val_test取出num_val个元素,val_test剩下的元素就是testval = random.sample(val_test, num_val)j = 0print("训练集数目:{}, 验证集数目:{}, 测试集数目:{}".format(len(train), len(val), len(val_test) - len(val)))for i in list_all_txt:name = total_txt[i][:-4]# name = total_txt[i]srcImage = image_original_path + name + '.jpg'if not os.path.exists(srcImage):print("no exist image",srcImage)# if not os.path.exists(srcImage):#     srcImage=srcImage.replace('.bmp','.jpg')#     if not os.path.exists(srcImage):#         srcImage = srcImage.replace('.jpg','.PNG')# srcImage = image_original_path + namesrcLabel = label_original_path + name + ".txt"print("j: ", j)j += 1if not os.path.exists(srcLabel):print("no exist label",srcLabel)if i in train:# dst_train_Image = train_image_path + namedst_train_Image = train_image_path + name + '.jpg'dst_train_Label = train_label_path + name + '.txt'shutil.copyfile(srcImage, dst_train_Image)shutil.copyfile(srcLabel, dst_train_Label)file_train.write(dst_train_Image + '\n')elif i in val:dst_val_Image = val_image_path + name + '.jpg'# dst_val_Image = val_image_path + namedst_val_Label = val_label_path + name + '.txt'shutil.copyfile(srcImage, dst_val_Image)shutil.copyfile(srcLabel, dst_val_Label)file_val.write(dst_val_Image + '\n')else:# dst_test_Image = test_image_path + name + '.bmp'dst_test_Image = test_image_path + name + '.jpg'dst_test_Label = test_label_path + name + '.txt'shutil.copyfile(srcImage, dst_test_Image)shutil.copyfile(srcLabel, dst_test_Label)file_test.write(dst_test_Image + '\n')file_train.close()file_val.close()file_test.close()if __name__ == "__main__":main()
图4-3

五、yolov7模型训练

pycharm 打开我们的 yolov7 文件夹,打开 cfg/training/yolov7x.yaml 文件夹修改 nc 变量的值为 1,这是我们的训练类别,我们只标注了一类,因此只训练一类,修改后的 yolov7x.yaml 文件如图5-1所示。

图5-1

打开 data/coco.yaml 文件夹,修改如图5-2所示,trainvaltest 对应的txt路径是我们之前生成的含有图像、标签等路径的txt文件路径,names 的值为你标注时的标签名称。 

图5-2

 打开 train.py ,修改如图5-3所示,主要是修改 --weights、--cfg、--data、--hyp、--epochs、--batch-size、--device、--workers 等参数的默认值,若训练时报显存不足的错误,可以把--batch-size--workers的值改小一点,直到能够训练,也能改--img-size的值为 [320, 320]

图5-3

 这一步做完之后就可以开始训练了,这一步是最消耗时间的,训练完成之后,打开 runs/train/exp/weights ,训练好的模型文件就在里面,我们需要的是 best.pt 这个权重文件

六、.pt权重文件转.onnx模型

这里为什么要用 .onnx 模型文件而不是用 .pt 模型文件呢, 主要是 .onnx 模型文件可以部署在各种环境里,速度还比较快。把训练好的 best.pt 权重文件放入到 weights 文件夹里,打开 export.py ,此处只需要修改 --weights、--device 参数的默认值即可,修改如图6-1所示,运行结果就在 weights 文件夹里,best.onnx 就是我们最后需要的权重文件。

图6-1

图6-2

七、onnx模型推理与鼠标控制 

1、使用 mss 模块实时截取屏幕保存到本地,使用 cv2 读取图像。

代码:

img = m.grab(rect)
mt.to_png(img.rgb, img.size, 6, "result_img/Image_.jpg")
image = cv2.imread("result_img/Image_.jpg")
print("grab screen with {0} pictures.".format(i))

2、 onnx 模型推理 cv2 读取到的图像

onnx初始化代码:

cuda = True
w = "weights/best.onnx"
providers = ['CUDAExecutionProvider', 'CPUExecutionProvider'] if cuda else ['CPUExecutionProvider']
session = ort.InferenceSession(w, providers=providers)
outname = [i.name for i in session.get_outputs()]
print(outname)inname = [i.name for i in session.get_inputs()]
print(inname)

识别名称跟矩形框随机颜色代码:

names = ['enemy']
colors = {name:[random.randint(0, 255) for _ in range(3)] for i,name in enumerate(names)}

yolov7图像自适应缩放代码:

def letterbox(im, new_shape=(640, 640), color=(114, 114, 114), auto=True, scaleup=True, stride=32):# Resize and pad image while meeting stride-multiple constraintsshape = im.shape[:2]  # current shape [height, width]if isinstance(new_shape, int):new_shape = (new_shape, new_shape)# Scale ratio (new / old)r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])if not scaleup:  # only scale down, do not scale up (for better val mAP)r = min(r, 1.0)# Compute paddingnew_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]  # wh paddingif auto:  # minimum rectangledw, dh = np.mod(dw, stride), np.mod(dh, stride)  # wh paddingdw /= 2  # divide padding into 2 sidesdh /= 2if shape[::-1] != new_unpad:  # resizeim = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))left, right = int(round(dw - 0.1)), int(round(dw + 0.1))im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)  # add borderreturn im, r, (dw, dh)

onnx推理代码: 

def detect():j = 1while True:t0 = time.time()t1 = time.time()img = screen_record(j)print("runs_time: ", (time.time() - t1)*1000)j += 1#img = cv2.imread("C:\\Users\\Admin\\Desktop\\test\\images\\Image_2023-05-19_18-46-56.png")#img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)image, ratio, dwdh = letterbox(img, auto=False)image = image.transpose((2, 0, 1))image = np.expand_dims(image, 0)image = np.ascontiguousarray(image)im = image.astype(np.float32)im /= 255inp = {inname[0]: im}outputs = session.run(outname, inp)[0]ori_images = [img.copy()]center_xy = []distance = []for i, (batch_id, x0, y0, x1, y1, cls_id, score) in enumerate(outputs):image = ori_images[int(batch_id)]box = np.array([x0, y0, x1, y1])box -= np.array(dwdh * 2)box /= ratiobox = box.round().astype(np.int32).tolist()cls_id = int(cls_id)score = round(float(score), 3)name = names[cls_id]color = colors[name]name += ' ' + str(score) + str(box)if score > 0.5:cv2.rectangle(image, box[:2], box[2:], color, 2)cv2.putText(image, name, (box[0], box[1] - 2), cv2.FONT_HERSHEY_SIMPLEX, 0.75, [225, 255, 255],thickness=2)if len(outputs)>0:#image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)cv2.imwrite("C:\\Users\\Admin\\Desktop\\test\\result_img\\{0}.jpg".format(str(time.strftime("%Y_%m_%d_%H_%M_%S", time.localtime()))), image)

3、计算各个人物中心坐标,并计算其与鼠标的距离判断距离鼠标最近的人物

计算距离代码:

# 传入两个坐标点,计算直线距离的
class Point:def __init__(self, x1, y1, x2, y2):self.x1 = x1self.y1 = y1self.x2 = x2self.y2 = y2class Line(Point):def __init__(self, x1, y1, x2, y2):super().__init__(x1, y1, x2, y2)def getlen(self):return math.sqrt(math.pow((self.x1 - self.x2), 2) + math.pow((self.y1 - self.y2), 2))
if score > 0.5:# 获取识别出来的人物中心点 x, ycenter_x = ((box[2] - box[0]) / 2) + box[0]center_y = ((box[3] - box[1]) / 2) + box[1]center_xy.append((int(center_x), int(center_y)))

4、获取鼠标位置并控制鼠标移动到人物中心 

代码:

 # 获取当前鼠标所在位置mouse_control = Controller()if len(center_xy) != 0:for center_x, center_y in center_xy:L1 = Line( mouse_control.position[0],  mouse_control.position[1], center_x, center_y)distance.append(L1.getlen())print(" orginal mouse_control.position: ", mouse_control.position)print("center_xy: ", center_xy[distance.index(min(distance))])#mouse_control.move(center_x - mouse_x, center_y - mouse_y)move_x = int(center_xy[distance.index(min(distance))][0] - mouse_control.position[0])move_y = int(center_xy[distance.index(min(distance))][1] - mouse_control.position[1])  #敌人y坐标 - (屏幕高度 - (敌人最大y坐标 - 敌人最小y坐标) / 2)win32api.mouse_event(win32con.MOUSEEVENTF_MOVE, move_x, move_y, 0, 0)print(" move mouse_control.position: ",  mouse_control.position)

  5、onnx模型推理与鼠标控制总代码 

代码:

import mss.tools
import mss
from pynput.mouse import Controller
import time
import cv2
import numpy as np
import random
import onnxruntime as ort
import mathimport win32api
import win32congame_width = 2560
game_height = 1440rect = (0, 0, game_width, game_height)
m = mss.mss()
mt = mss.toolscuda = True
w = "best.onnx"
providers = ["CUDAExecutionProvider", "CPUExecutionProvider"] if cuda else["CPUExecutionProvider"]session = ort.InferenceSession(w, providers=providers)
outname = [i.name for i in session.get_outputs()]
print(outname)inname = [i.name for i in session.get_inputs()]
print(inname)names = ["enemy"]
colors = {name : [random.randint(0, 255) for _ in range(3)] for i,name in enumerate(names)}# 传入两个坐标点,计算直线距离的
class Point:def __init__(self, x1, y1, x2, y2):self.x1 = x1self.y1 = y1self.x2 = x2self.y2 = y2class Line(Point):def __init__(self, x1, y1, x2, y2):super().__init__(x1, y1, x2, y2)def getlen(self):return math.sqrt(math.pow((self.x1 - self.x2), 2) + math.pow((self.y1 - self.y2), 2))# 截图保存
def screen_record(i):img = m.grab(rect)mt.to_png(img.rgb, img.size, 6, "result_img/Image_.jpg")image = cv2.imread("result_img/Image_.jpg")#img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)print("grab screen with {0} pictures.".format(i))return imagedef letterbox(im, new_shape=(320, 320), color=(114, 114, 114), auto=True, scaleup=True, stride=32):# Resize and pad image while meeting stride-multiple constraintsshape = im.shape[:2]  # current shape [height, width]if isinstance(new_shape, int):new_shape = (new_shape, new_shape)# Scale ratio (new / old)r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])if not scaleup:  # only scale down, do not scale up (for better val mAP)r = min(r, 1.0)# Compute paddingnew_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]  # wh paddingif auto:  # minimum rectangledw, dh = np.mod(dw, stride), np.mod(dh, stride)  # wh paddingdw /= 2  # divide padding into 2 sidesdh /= 2if shape[::-1] != new_unpad:  # resizeim = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))left, right = int(round(dw - 0.1)), int(round(dw + 0.1))im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)  # add borderreturn im, r, (dw, dh)def detect():j = 1while True:t0 = time.time()t1 = time.time()img = screen_record(j)print("runs_time: ", (time.time() - t1)*1000)j += 1#img = cv2.imread("C:\\Users\\Admin\\Desktop\\test\\images\\Image_2023-05-19_18-46-56.png")#img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)image, ratio, dwdh = letterbox(img, auto=False)image = image.transpose((2, 0, 1))image = np.expand_dims(image, 0)image = np.ascontiguousarray(image)im = image.astype(np.float32)im /= 255inp = {inname[0]: im}outputs = session.run(outname, inp)[0]ori_images = [img.copy()]center_xy = []distance = []for i, (batch_id, x0, y0, x1, y1, cls_id, score) in enumerate(outputs):image = ori_images[int(batch_id)]box = np.array([x0, y0, x1, y1])box -= np.array(dwdh * 2)box /= ratiobox = box.round().astype(np.int32).tolist()cls_id = int(cls_id)score = round(float(score), 3)name = names[cls_id]color = colors[name]name += ' ' + str(score) + str(box)if score > 0.5:cv2.rectangle(image, box[:2], box[2:], color, 2)cv2.putText(image, name, (box[0], box[1] - 2), cv2.FONT_HERSHEY_SIMPLEX, 0.75, [225, 255, 255],thickness=2)if len(outputs)>0:#image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)cv2.imwrite("C:\\Users\\Admin\\Desktop\\test\\result_img\\{0}.jpg".format(str(time.strftime("%Y_%m_%d_%H_%M_%S", time.localtime()))), image)if score > 0.5:# 获取识别出来的人物中心点 x, ycenter_x = ((box[2] - box[0]) / 2) + box[0]center_y = ((box[3] - box[1]) / 2) + box[1]center_xy.append((int(center_x), int(center_y)))# 获取当前鼠标所在位置mouse_control = Controller()if len(center_xy) != 0:for center_x, center_y in center_xy:L1 = Line( mouse_control.position[0],  mouse_control.position[1], center_x, center_y)distance.append(L1.getlen())print(" orginal mouse_control.position: ", mouse_control.position)print("center_xy: ", center_xy[distance.index(min(distance))])#mouse_control.move(center_x - mouse_x, center_y - mouse_y)move_x = int(center_xy[distance.index(min(distance))][0] - mouse_control.position[0])move_y = int(center_xy[distance.index(min(distance))][1] - mouse_control.position[1])  #敌人y坐标 - (屏幕高度 - (敌人最大y坐标 - 敌人最小y坐标) / 2)win32api.mouse_event(win32con.MOUSEEVENTF_MOVE, move_x, move_y, 0, 0)print(" move mouse_control.position: ",  mouse_control.position)#sys.exit()print("inference time is:", time.time() - t0)print("\n")def main():detect()if __name__ == "__main__":main()

推理识别结果:

图7-1

为了更好的展示效果,截图暂停300ms的时间:

Crossfire


总结

整个项目有两点需要特别注意:

1、pt 模型文件转 onnx 模型文件时,img-size参数应该一致;

2、若显存不足,则修改图像大小及关闭nvidia experence中的重放功能和录制功能;

3、游戏中控制鼠标移动时应该使用的是相对移动,而不是绝对位置,不然是无效移动;

4、应该使用管理员权限来运行程序,不然不能在游戏中控制鼠标;

项目需要改进的地方有:

1、截图模块需要改进,项目里使用的是 pynput 进行截图,消耗的时间有30毫秒,听说用 Qt 或者 win32 的接口来截图时间会更少,但是我没有去试过;

2、项目运行时,不可避免的会有一些误判,应该想办法去解决,比如提高置信度阈值或者根据面积大小来做阈值;

3、总的消耗时间大概是 100ms ,还有很大的优化空间。

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

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

相关文章

阿里国际站商品发布odoo插件

阿里国际站商品发布odoo插件,支持全新的阿里api接口,支持手动批量,预约发布,功能强大,可支持odoo13 14版本,自行开发,提供源码,售后支持服务。 可试用。

iOS 集成阿里百川最新版(3.1.1.96) 实现淘宝授权登录以及调用淘宝客户端商品详情页...

公司最近要做第三方登录,由于是做导购项目,必不可少的有淘宝的授权登录。本来就是一个授权登录,没什么大不了的。但淘宝的无线开放业务——阿里百川更新的最新版本3.1.1.96,开发文档不是不详细,是很不详细。于是乎就自…

电商直播风起,阿里再次大象起舞

“大象跳舞”这个说法被大家所熟知,始自于IBM前任CEO郭士纳的自传《谁说大象不能跳舞(Who Says Elephants Can’t Dance?)》,在这本书中,郭士纳详实地介绍了他如何通过一步步改革让IBM起死回生,…

阿里巴巴发布AliGenie 语音开放平台 “智联网”战略又落一子

10月12日消息,在2017杭州•云栖大会上,阿里巴巴人工智能实验室发布了AliGenie 开放平台,主要包括三大部分:精灵技能市场、硬件开放平台、行业解决方案,全面赋能智能家居、新制造、新零售、酒店、航空等服务场景。 阿里…

阿里巴巴最新开源软件列表(建议收藏系列)

阿里的开源项目很多,这也跟@淘宝正明的开源态度密不可分。 有很多重量级的项目,例如LVS、Tengine,或者很有实践价值的中间件 今天小编为大家汇总了阿里开源的项目,快来看看吧! 服务框架 Dubbo Dubbo 是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能…

阿里推送以及厂商推送

oppo通道 在阿里控制台配置MasterSecret,和oppo平台的appserversecret一样,需要登录到oppo开放平台里的推送平台,配置8.0的渠道,否则8.0以上收不到通知,注意私信和公信的区别,私信需要申请开通。 先在oppo…

阿里巴巴发布 AliGenie 语音开放平台「智联网」战略又落一子

10 月 12 日消息,在 2017 杭州•云栖大会上,阿里巴巴人工智能实验室发布了 AliGenie 开放平台,主要包括三大部分:精灵技能市场、硬件开放平台、行业解决方案,全面赋能智能家居、新制造、新零售、酒店、航空等服务场景。…

阿里巴巴与淘宝网今日起帐号实现互通

阿里巴巴集团今日发布公告称,自即日起,阿里巴巴与淘宝网的帐号将实现互通。阿里巴巴方面介绍,用户在阿里巴巴中国站或淘宝网已经注册过会员帐号,可以使用任意一个帐号同时在阿里巴巴和淘宝网处于登录状态。不过,帐号互…

阿里巴巴开源产品列表

代码:https://github.com/alibaba taobao-kernel http://kernel.taobao.org/ https://github.com/alibaba/taobao-kernel 淘宝内核是淘宝内核开发团队基于RHEL6官方内核自己定制的内核,他与RHEL6系列内核的主要区别包括: 1. 修改了一些…

美厂商Equinix与阿里云达成合作 将提供云访问服务

美厂商Equinix与阿里云达成合作 将提供云访问服务 责任编辑:editor005 作者:茹亚飞编译 | 2017-06-16 14:32:20 本文摘自:环球网 据外媒6月13日报道,全球互联数据中心Equinix公司宣布与阿里巴巴集团云计算部门阿里云达成合作&a…

阿里云EMAS超级App助力Agmo电动车超级应用程序发布

近日,阿里云宣布与马来西亚本土数字方案专家Agmo控股(Agmo Holdings Berhad,简称Agmo)展开合作,签署谅解备忘录,联手推出马来西亚首个Agmo电动车超级应用程序。此次合作也标志着阿里云在中国以外的市场首次…

阿里巴巴中国站手机客户端项目总结

自:http://www.aliued.cn/2012/01/18/%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B4%E6%89%8B%E6%9C%BA%E5%AE%A2%E6%88%B7%E7%AB%AF%E9%A1%B9%E7%9B%AE%E6%80%BB%E7%BB%93.html 阿里巴巴中国站手机客户端项目总结 by liuchenhuan— 交互设计 | 2012-01-18 阿里巴巴手机客…

超级浏览器能帮来赞达(Lazada)老板什么忙?

近几年东南亚市场因人口红利及互联网的高度普及倍受关注,东南亚市场成了跨境市场的香饽饽,像来赞达(Lazada)、虾皮(shopee)等平台都是最近东南亚地区比较受欢迎的在线购物网站。 根据第三方发布的调查报告显…

阿里巴巴牵头发起对雅虎的250亿美元并购

近日有消息透露,阿里巴巴正携软银集团,就竞购雅虎全部业务与黑石及贝恩资本进行深入谈判,黑石集团和贝恩资本同意与阿里巴巴集团、日本软银联手,并牵头发起对雅虎全部股权的竞购。前二者希望收购雅虎的美国业务。有知情人士向本报…

车联网布局,阿里领先了百度腾讯多少?

高票的匿名回答虽然充满了吃瓜群众的八卦,看起来满是“小道”消息,但其实本质的结论和表达的意思其实和我了解的并没有太大的出入。在目前看来,阿里的AliOS在车联系统领域确实是领先的,毕竟从几年前就开始布局,又有斑马…

解决chrome浏览器无法自动调用阿里旺旺客户端聊天软件

2019独角兽企业重金招聘Python工程师标准>>> 解决chrome浏览器无法自动调用阿里旺旺客户端聊天软件 复制粘贴以下代码,可以直达设置页面 chrome://settings/contentExceptions#plugins 打开chrome浏览器---设置---显示高级设置---隐私管理[内容管理]---…

计算机专业学生社会实践,计算机专业学生社会实践报告

计算机专业学生社会实践报告 篇1: 看着四年的大学生活就快要结束了,心中隐隐有一种伤感与失落,我陷入了沉思:该挺直腰杆走自己的路了!学习嵌入式是我的梦想,我很羡慕能够在嵌入式方面独档一面的高手,希望有…

Java社会实践报告范文精选5篇

Java社会实践报告范文精选5篇 Java社会实践报告1 面临毕业与就业的压力,不久将来就要从一个学生到一个社会人的转变:技术在不断的提高,思路在不断的开阔,思想在不断的升华,更重要的是自己的理想和抱负更加的坚定。对于…

社会实践调查报告

电子科技大学 社会实践调查报告 题    目:微信、QQ的使用情况 学    院:格拉斯哥学院 专业班级:通信工程三班 小组成员:郭又铭2018190603014 刘文成2018190603017 许家暠2018190603025 李晓宁2018190603020 张正韬201…

DB-GPT:强强联合Langchain-Vicuna的应用实战开源项目,彻底改变与数据库的交互方式

今天看到 蚂蚁科技 Magic 开源的DB-GPT项目,觉得创意很好,集成了当前LLM的主流技术,主要如下 Langchain: 构建在LLM之上的应用开发框架HuggingFace: 模型标准,提供大模型管理功能Vicuna: 一个令GPT-4惊艳的开源聊天机…