diff --git a/Samples/HandWritingTrainAndInfer/README.md b/Samples/HandWritingTrainAndInfer/README.md index 36fd05b288ed7cb2e507cbca4b2cc788499aea2f..9acfa3d9fe559e64becf70d01e5d4774025119fa 100644 --- a/Samples/HandWritingTrainAndInfer/README.md +++ b/Samples/HandWritingTrainAndInfer/README.md @@ -34,6 +34,13 @@ #### 准备环境 - 本样例中的模型支持PyTorch2.1.0、torchvision1.16.0版本,请参考[安装PyTorch](https://www.hiascend.com/document/detail/zh/canncommercial/700/envdeployment/instg/instg_0046.html)章节安装PyTorch以及torch_npu插件。 + ``` + # torch_npu由于需要源码编译,速度可能较慢,本样例提供 python3.9,torch2.1版本的torch_npu whl包 + wget https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/wanzutao/torch_npu-2.1.0rc1-cp39-cp39-linux_aarch64.whl + + # 使用pip命令安装 + pip3 install torch_npu-2.1.0rc1-cp39-cp39-linux_aarch64.whl + ``` - 本样例中的模型还依赖一些其它库(具体依赖哪些库,可查看本样例目录下的requirements.txt文件),可执行以下命令安装: diff --git a/Samples/HandWritingTrainAndInfer/main.py b/Samples/HandWritingTrainAndInfer/main.py index 70c21dd3404b9786993ceaa0407ee3851b52219e..a695e282593f8e5b8a074d5f67c8647fc32981d4 100644 --- a/Samples/HandWritingTrainAndInfer/main.py +++ b/Samples/HandWritingTrainAndInfer/main.py @@ -14,12 +14,15 @@ device = torch.device('npu:0') #torch.npu.set_compile_mode(jit_compile=False) #option = {"MM_BMM_ND_ENABLE":"disable"} #torch_npu.npu.set_option(option) + + class Summary(Enum): NONE = 0 AVERAGE = 1 SUM = 2 COUNT = 3 + class ProgressMeter(object): def __init__(self, num_batches, meters, prefix=""): self.batch_fmtstr = self._get_batch_fmtstr(num_batches) @@ -111,6 +114,43 @@ def accuracy(output, target, topk=(1,)): return res +def train(train_dataloader, model, criterion, optimizer , epoch): + batch_time = AverageMeter('Time', ':6.3f') + data_time = AverageMeter('Data', ':6.3f') + losses = AverageMeter('Loss', ':.4e') + top1 = AverageMeter('Acc@1', ':6.2f') + top5 = AverageMeter('Acc@5', ':6.2f') + progress = ProgressMeter( + len(train_dataloader), + [batch_time, data_time, losses, top1, top5], + prefix="Epoch: [{}]".format(epoch)) + end = time.time() + for batch_idx,(imgs, labels) in enumerate(train_dataloader): + data_time.update(time.time() - end) + imgs = imgs.to(device) # 把img数据放到指定NPU上 + labels = labels.to(device) # 把label数据放到指定NPU上 + with amp.autocast(): # 设置amp + outputs = model(imgs) # 前向计算 + loss = criterion(outputs, labels) # 损失函数计算 + optimizer.zero_grad() + # 进行反向传播前后的loss缩放、参数更新 + scaler.scale(loss).backward() # loss缩放并反向转播 + scaler.step(optimizer) # 更新参数(自动unscaling) + scaler.update() # 基于动态Loss Scale更新loss_scaling系数 + + acc1, acc5 = accuracy(outputs, labels, topk=(1, 5)) + losses.update(loss.item(), imgs.size(0)) + top1.update(acc1[0], imgs.size(0)) + top5.update(acc5[0], imgs.size(0)) + batch_time.update(time.time() - end) + end = time.time() + if batch_idx % 50 == 0: + progress.display(batch_idx + 1) + print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format( + epoch, batch_idx * len(imgs), len(train_dataloader.dataset), + 100. * batch_idx / len(train_dataloader), loss.item())) + + class CNN(nn.Module): def __init__(self): super(CNN, self).__init__() @@ -142,45 +182,10 @@ batch_size = 64 model = CNN().to(device) # 把模型放到指定NPU上 train_dataloader = DataLoader(train_data, batch_size=batch_size) # 定义DataLoader loss_func = nn.CrossEntropyLoss().to(device) # 定义损失函数 -optimizer = torch.optim.SGD(model.parameters(), lr=0.1) # 定义优化器 +optimizer = torch.optim.SGD(model.parameters(), lr = 0.1) # 定义优化器 scaler = amp.GradScaler() # 在模型、优化器定义之后,定义GradScaler epochs = 10 # 设置循环次数 -batch_time = AverageMeter('Time', ':6.3f') -data_time = AverageMeter('Data', ':6.3f') -losses = AverageMeter('Loss', ':.4e') -top1 = AverageMeter('Acc@1', ':6.2f') -top5 = AverageMeter('Acc@5', ':6.2f') -outputs = None -loss = None + for epoch in range(epochs): - progress = ProgressMeter( - len(train_dataloader), - [batch_time, data_time, losses, top1, top5], - prefix="Epoch: [{}]".format(epoch)) - end = time.time() - for batch_idx,(imgs, labels) in enumerate(train_dataloader): - data_time.update(time.time() - end) - start_time = time.time() - imgs = imgs.to(device) # 把img数据放到指定NPU上 - labels = labels.to(device) # 把label数据放到指定NPU上 - with amp.autocast(): # 设置amp - outputs = model(imgs) # 前向计算 - loss = loss_func(outputs, labels) # 损失函数计算 - optimizer.zero_grad() - # 进行反向传播前后的loss缩放、参数更新 - scaler.scale(loss).backward() # loss缩放并反向转播 - scaler.step(optimizer) # 更新参数(自动unscaling) - scaler.update() # 基于动态Loss Scale更新loss_scaling系数 - - acc1, acc5 = accuracy(outputs, labels, topk=(1, 5)) - losses.update(loss.item(), imgs.size(0)) - top1.update(acc1[0], imgs.size(0)) - top5.update(acc5[0], imgs.size(0)) - batch_time.update(time.time() - end) - end = time.time() - if batch_idx % 50 == 0: - progress.display(batch_idx + 1) - print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format( - epoch, batch_idx * len(imgs), len(train_dataloader.dataset), - 100. * batch_idx / len(train_dataloader), loss.item())) + train(train_dataloader, model, loss_func, optimizer, epoch) torch.save(model,"./mnist.pt") diff --git a/Samples/HandWritingTrainAndInfer/main_cpu.py b/Samples/HandWritingTrainAndInfer/main_cpu.py index 5f0fe900e586e6e599de37d81cfee0b31e1ad451..755749da46c12b504cb3f3bebe017b3af904ac5c 100644 --- a/Samples/HandWritingTrainAndInfer/main_cpu.py +++ b/Samples/HandWritingTrainAndInfer/main_cpu.py @@ -100,7 +100,38 @@ def accuracy(output, target, topk=(1,)): res.append(correct_k.mul_(100.0 / batch_size)) return res - +def train(train_loader, model, criterion, optimizer , epoch): + batch_time = AverageMeter('Time', ':6.3f') + data_time = AverageMeter('Data', ':6.3f') + losses = AverageMeter('Loss', ':.4e') + top1 = AverageMeter('Acc@1', ':6.2f') + top5 = AverageMeter('Acc@5', ':6.2f') + progress = ProgressMeter( + len(train_dataloader), + [batch_time, data_time, losses, top1, top5], + prefix="Epoch: [{}]".format(epoch)) + end = time.time() + for batch_idx,(imgs, labels) in enumerate(train_dataloader): + data_time.update(time.time() - end) + outputs = model(imgs) # 前向计算 + loss = criterion(outputs, labels) # 损失函数计算 + optimizer.zero_grad() + loss.backward() # 损失函数反向计算 + optimizer.step() # 更新优化器 + + acc1, acc5 = accuracy(outputs, labels, topk=(1, 5)) + losses.update(loss.item(), imgs.size(0)) + top1.update(acc1[0], imgs.size(0)) + top5.update(acc5[0], imgs.size(0)) + batch_time.update(time.time() - end) + end = time.time() + if batch_idx % 50 == 0: + progress.display(batch_idx + 1) + print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format( + epoch, batch_idx * len(imgs), len(train_dataloader.dataset), + 100. * batch_idx / len(train_dataloader), loss.item())) + + # 定义一个简单的神经网络 class CNN(nn.Module): def __init__(self): @@ -143,32 +174,7 @@ optimizer = torch.optim.SGD(model.parameters(), lr = 0.1) # 设置循环 epochs = 10 -batch_time = AverageMeter('Time', ':6.3f') -data_time = AverageMeter('Data', ':6.3f') -losses = AverageMeter('Loss', ':.4e') -top1 = AverageMeter('Acc@1', ':6.2f') -top5 = AverageMeter('Acc@5', ':6.2f') for epoch in range(epochs): - progress = ProgressMeter( - len(train_dataloader), - [batch_time, data_time, losses, top1, top5], - prefix="Epoch: [{}]".format(epoch)) - end = time.time() - for batch_idx,(imgs, labels) in enumerate(train_dataloader): - data_time.update(time.time() - end) - outputs = model(imgs) # 前向计算 - loss = loss_func(outputs, labels) # 损失函数计算 - optimizer.zero_grad() - loss.backward() # 损失函数反向计算 - optimizer.step() # 更新优化器 - - acc1, acc5 = accuracy(outputs, labels, topk=(1, 5)) - losses.update(loss.item(), imgs.size(0)) - top1.update(acc1[0], imgs.size(0)) - top5.update(acc5[0], imgs.size(0)) - batch_time.update(time.time() - end) - end = time.time() - if batch_idx % 50 == 0: - progress.display(batch_idx + 1) + train(train_dataloader, model, loss_func, optimizer, epoch) PATH = "mnist.pt" # 创建保存路径 torch.save(model, PATH) # 保存模型 \ No newline at end of file diff --git a/Samples/HandWritingTrainAndInfer/main_emnist.py b/Samples/HandWritingTrainAndInfer/main_emnist.py new file mode 100644 index 0000000000000000000000000000000000000000..b5c3787d012a3f9b805baaf430d8e0ddd42ecbed --- /dev/null +++ b/Samples/HandWritingTrainAndInfer/main_emnist.py @@ -0,0 +1,262 @@ +# 引入模块 +import time +import torch +import torch.nn as nn +import torch_npu +# 导入AMP模块 +from torch_npu.npu import amp +from torch.utils.data import Dataset, DataLoader +import torchvision +from enum import Enum + +#指定运行Device,用户请自行定义训练设备 +device = torch.device('npu:0') +#torch.npu.set_compile_mode(jit_compile=False) +#option = {"MM_BMM_ND_ENABLE":"disable"} +#torch_npu.npu.set_option(option) +LOG_STEP = 10 + + +class Summary(Enum): + NONE = 0 + AVERAGE = 1 + SUM = 2 + COUNT = 3 + + +class ProgressMeter(object): + def __init__(self, num_batches, meters, prefix=""): + self.batch_fmtstr = self._get_batch_fmtstr(num_batches) + self.meters = meters + self.prefix = prefix + + def display(self, batch): + entries = [self.prefix + self.batch_fmtstr.format(batch)] + entries += [str(meter) for meter in self.meters] + print('\t'.join(entries)) + + def display_summary(self): + entries = [" *"] + entries += [meter.summary() for meter in self.meters] + print(' '.join(entries)) + + def _get_batch_fmtstr(self, num_batches): + num_digits = len(str(num_batches // 1)) + fmt = '{:' + str(num_digits) + 'd}' + return '[' + fmt + '/' + fmt.format(num_batches) + ']' + + +class AverageMeter(object): + """Computes and stores the average and current value""" + + def __init__(self, name, fmt=':f', summary_type=Summary.AVERAGE): + self.name = name + self.fmt = fmt + self.summary_type = summary_type + self.reset() + + def reset(self): + self.val = 0 + self.avg = 0 + self.sum = 0 + self.count = 0 + + def update(self, val, n=1): + self.val = val + self.sum += val * n + self.count += n + self.avg = self.sum / self.count + + def all_reduce(self): + if torch.npu.is_available(): + device = torch.device("npu") + elif torch.backends.mps.is_available(): + device = torch.device("mps") + else: + device = torch.device("cpu") + total = torch.tensor([self.sum, self.count], dtype=torch.float32, device=device) + dist.all_reduce(total, dist.ReduceOp.SUM, async_op=False) + self.sum, self.count = total.tolist() + self.avg = self.sum / self.count + + def __str__(self): + fmtstr = '{name} {val' + self.fmt + '} ({avg' + self.fmt + '})' + return fmtstr.format(**self.__dict__) + + def summary(self): + fmtstr = '' + if self.summary_type is Summary.NONE: + fmtstr = '' + elif self.summary_type is Summary.AVERAGE: + fmtstr = '{name} {avg:.3f}' + elif self.summary_type is Summary.SUM: + fmtstr = '{name} {sum:.3f}' + elif self.summary_type is Summary.COUNT: + fmtstr = '{name} {count:.3f}' + else: + raise ValueError('invalid summary type %r' % self.summary_type) + + return fmtstr.format(**self.__dict__) + +def accuracy(output, target, topk=(1,)): + """Computes the accuracy over the k top predictions for the specified values of k""" + with torch.no_grad(): + maxk = max(topk) + batch_size = target.size(0) + + _, pred = output.topk(maxk, 1, True, True) + pred = pred.t() + correct = pred.eq(target.view(1, -1).expand_as(pred)) + + res = [] + for k in topk: + correct_k = correct[:k].reshape(-1).float().sum(0, keepdim=True) + res.append(correct_k.mul_(100.0 / batch_size)) + return res + +def validate(val_loader, model, criterion): + batch_time = AverageMeter('Time', ':6.3f') + losses = AverageMeter('Loss', ':.4e') + top1 = AverageMeter('Acc@1', ':6.2f') + top5 = AverageMeter('Acc@5', ':6.2f') + progress = ProgressMeter( + len(val_loader), + [batch_time, losses, top1, top5], + prefix='Test: ') + + # switch to evaluate mode + model.eval() + + with torch.no_grad(): + end = time.time() + for i, (images, target) in enumerate(val_loader): + if i > 50: + pass + images = images.to(device, non_blocking=True) + target = target.to(torch.int32).to(device, non_blocking=True) + # compute output + with amp.autocast(): + output = model(images) + loss = criterion(output, target) + + # measure accuracy and record loss + acc1, acc5 = accuracy(output, target, topk=(1, 5)) + losses.update(loss.item(), images.size(0)) + top1.update(acc1[0], images.size(0)) + top5.update(acc5[0], images.size(0)) + + # measure elapsed time + batch_time.update(time.time() - end) + end = time.time() + + if i % LOG_STEP == 0: + progress.display(i) + + print(' * Acc@1 {top1.avg:.3f} Acc@5 {top5.avg:.3f}' + .format(top1=top1, top5=top5)) + return top1.avg + +def train(train_loader, model, criterion, optimizer , epoch): + model.train() # 切换训练模式 + + batch_time = AverageMeter('Time', ':6.3f') + data_time = AverageMeter('Data', ':6.3f') + losses = AverageMeter('Loss', ':.4e') + top1 = AverageMeter('Acc@1', ':6.2f') + top5 = AverageMeter('Acc@5', ':6.2f') + progress = ProgressMeter( + len(train_dataloader), + [batch_time, data_time, losses, top1, top5], + prefix="Epoch: [{}]".format(epoch)) + + end = time.time() + for batch_idx,(imgs, labels) in enumerate(train_dataloader): + data_time.update(time.time() - end) + start_time = time.time() + imgs = imgs.to(device) # 把img数据放到指定NPU上 + labels = labels.to(device) # 把label数据放到指定NPU上 + with amp.autocast(): # 设置amp + outputs = model(imgs) # 前向计算 + loss = loss_func(outputs, labels) # 损失函数计算 + optimizer.zero_grad() + # 进行反向传播前后的loss缩放、参数更新 + scaler.scale(loss).backward() # loss缩放并反向转播 + scaler.step(optimizer) # 更新参数(自动unscaling) + scaler.update() # 基于动态Loss Scale更新loss_scaling系数 + + acc1, acc5 = accuracy(outputs, labels, topk=(1, 5)) + losses.update(loss.item(), imgs.size(0)) + top1.update(acc1[0], imgs.size(0)) + top5.update(acc5[0], imgs.size(0)) + batch_time.update(time.time() - end) + end = time.time() + if batch_idx % 50 == 0: + progress.display(batch_idx + 1) + print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format( + epoch, batch_idx * len(imgs), len(train_dataloader.dataset), + 100. * batch_idx / len(train_dataloader), loss.item())) + + +class CNN(nn.Module): + def __init__(self): + super(CNN, self).__init__() + self.net = nn.Sequential( + nn.Conv2d(in_channels = 1, out_channels = 16, + kernel_size = (5, 5), + stride = (1, 1), + padding = 2), + nn.ReLU(), + nn.MaxPool2d(kernel_size = 2), + nn.Conv2d(16, 32, 5, 1, 2), + nn.ReLU(), + nn.MaxPool2d(2), + nn.Flatten(), + nn.Linear(32*7*7, 27) + ) + def forward(self, x): + return self.net(x) + +# 数据集获取 +train_data = torchvision.datasets.EMNIST( + "./dataset", + split="letters", + download = True, + train = True, + transform = torchvision.transforms.Compose([ + torchvision.transforms.ToTensor(), + torchvision.transforms.RandomRotation(degrees=(90, 90)), + torchvision.transforms.RandomVerticalFlip(p=1), + ]) + +) + +val_data = torchvision.datasets.EMNIST( + "./dataset", + split="letters", + download = True, + train = False, + transform = torchvision.transforms.Compose([ + torchvision.transforms.ToTensor(), + torchvision.transforms.RandomRotation(degrees=(90, 90)), + torchvision.transforms.RandomVerticalFlip(p=1), + ]) +) + +# 定义训练相关参数 +best_acc1 = 0 +batch_size = 64 +model = CNN().to(device) # 把模型放到指定NPU上 +train_dataloader = DataLoader(train_data, batch_size=batch_size) # 定义DataLoader +val_dataloader = DataLoader(val_data, batch_size=batch_size) # 定义DataLoader +loss_func = nn.CrossEntropyLoss().to(device) # 定义损失函数 +optimizer = torch.optim.Adam(model.parameters(), lr=0.001) # 定义优化器 +scaler = amp.GradScaler() # 在模型、优化器定义之后,定义GradScaler +epochs = 10 # 设置循环次数 +for epoch in range(epochs): + train(train_dataloader, model, loss_func, optimizer, epoch) + acc1 = validate(val_dataloader, model, loss_func) + is_best = acc1 > best_acc1 + best_acc1 = max(acc1, best_acc1) + file_name = "emnist.pt" + torch.save(model,file_name) + diff --git a/Samples/YOLOV5MultiInput/scripts/sample_run.sh b/Samples/YOLOV5MultiInput/scripts/sample_run.sh index b56b8e823c77d4d4928c76845aba36d654399a6e..a75e8d5c5e1a0e5194085d3629aa91ef9674c0b5 100644 --- a/Samples/YOLOV5MultiInput/scripts/sample_run.sh +++ b/Samples/YOLOV5MultiInput/scripts/sample_run.sh @@ -4,7 +4,7 @@ ScriptPath="$( cd "$(dirname "$BASH_SOURCE")" ; pwd -P )" function main() { echo "[INFO] The sample starts to run" - running_command="./main" + running_command="./main imshow" cd ${ScriptPath}/../out ${running_command} if [ $? -ne 0 ];then diff --git a/Samples/YOLOV5MultiInput/src/main.cpp b/Samples/YOLOV5MultiInput/src/main.cpp index ac283ff39c4f0cdc709271977f82b8c03690ff6e..1dd9702625b4f3e3753252c740e79c92b82f8375 100644 --- a/Samples/YOLOV5MultiInput/src/main.cpp +++ b/Samples/YOLOV5MultiInput/src/main.cpp @@ -63,7 +63,7 @@ namespace { size_t imageInfoSize; void* imageInfoBuf; std::vector winNameList; - + std::string displayMode = ""; const static std::vector yolov3Label = { "person", "bicycle", "car", "motorbike", "aeroplane", "bus", "train", "truck", "boat", "traffic light", "fire hydrant", "stop sign", "parking meter", @@ -106,6 +106,22 @@ namespace { }; } + +bool Initparam(int argc, char *argv[]) +{ + DIR *dir; + int outputDisplay = 1; + if ((dir = opendir("./out")) == NULL) + system("mkdir ./out"); + int paramNum = 2; + if(argc != paramNum) { + LOG_PRINT("[ERROR] please choose output display mode: [./main imshow] [./main stdout]"); + return false; + } + displayMode = argv[outputDisplay]; + return true; +} + void Draw(cv::Mat &srcImg, int channel) { cv::Mat resizedImg; cv::resize(srcImg, resizedImg, cv::Size(fullScreenWidth/showNum, (fullScreenHeight-titleHeight)/showNum)); @@ -116,7 +132,7 @@ void Draw(cv::Mat &srcImg, int channel) { void GetResult(std::vector& inferOutputs, cv::Mat& srcImage, uint32_t modelWidth, uint32_t modelHeight, int channelId) -{ +{ float *detectData = static_cast(inferOutputs[0].data.get()); uint32_t* boxNum = static_cast(inferOutputs[1].data.get()); if (boxNum == nullptr) return; @@ -126,7 +142,7 @@ void GetResult(std::vector& inferOutputs, int srcHeight = srcImage.rows; float widthScale = (float)(srcWidth) / modelWidth; float heightScale = (float)(srcHeight) / modelHeight; - + string textPrint = "["; for (uint32_t i = 0; i < totalBox; i++) { cv::Point p1, p2; uint32_t score = uint32_t(detectData[totalBox * SCORE + i] * 100); @@ -139,11 +155,23 @@ void GetResult(std::vector& inferOutputs, p2.y = detectData[totalBox * BOTTOMRIGHTY + i] * heightScale; uint32_t objIndex = (uint32_t)detectData[totalBox * LABEL + i]; string text = yolov3Label[objIndex] + std::to_string(score) + "\%"; + textPrint = textPrint + text + " "; cv::rectangle(srcImage, p1, p2, colors[i % colors.size()], lineSolid); cv::putText(srcImage, text, cv::Point(p1.x, p1.y + labelOffset), cv::FONT_HERSHEY_COMPLEX, fountScale, fontColor); } - Draw(srcImage, channelId); + textPrint = textPrint + "]"; + if (displayMode == "imshow") { + Draw(srcImage, channelId); + } else if (displayMode == "stdout") { + if (textPrint == "[]") { + cout<<"Channel-" << channelId << "-result: "<<"none object detected."< cfg; - cfg.resize(16); - + cfg.resize(channelNum); pthread_t preTids[channelNum], exeTids, posTids; for(int i = 0; i < channelNum; i++) { cfg[i].deviceId = deviceId; @@ -301,17 +327,18 @@ int main() { pthread_create(&preTids[i], NULL, GetInput, (void*)&cfg[i]); } - for (int i = channelNum - 1; i >= 0; i--) { - std::string head = "window"; - string winName = head+to_string(i); - cv::namedWindow(winName, WINDOW_NORMAL); - int x = (channel[i] % showNum) * (fullScreenWidth/showNum); - int y = (channel[i] / showNum) * ((fullScreenHeight-titleHeight)/showNum); - cv::moveWindow(winName, x, y+titleHeight); - cv::resizeWindow(winName, fullScreenWidth/showNum, (fullScreenHeight-titleHeight)/showNum); - winNameList.push_back(winName); + if (displayMode == "imshow") { + for (int i = channelNum - 1; i >= 0; i--) { + std::string head = "window"; + string winName = head+to_string(i); + cv::namedWindow(winName, WINDOW_NORMAL); + int x = (channel[i] % showNum) * (fullScreenWidth/showNum); + int y = (channel[i] / showNum) * ((fullScreenHeight-titleHeight)/showNum); + cv::moveWindow(winName, x, y+titleHeight); + cv::resizeWindow(winName, fullScreenWidth/showNum, (fullScreenHeight-titleHeight)/showNum); + winNameList.push_back(winName); + } } - pthread_create(&exeTids, NULL, ModelExecute, (void*)&channelNum); pthread_create(&posTids, NULL, PostProcess, NULL); diff --git a/Samples/YOLOV5USBCamera/README.md b/Samples/YOLOV5USBCamera/README.md index 7effbabaf0bb655857b179aa2d2ddb4776d50831..f28736abee4e7a963867bd35af5caf11508820b4 100644 --- a/Samples/YOLOV5USBCamera/README.md +++ b/Samples/YOLOV5USBCamera/README.md @@ -2,7 +2,8 @@ #### 样例介绍 -通过USB接口连接Camera与开发板,从Camera获取视频,基于yolov5s模型对输入视频中的物体做实时检测,将推理结果信息使用imshow方式显示。 +通过USB接口连接Camera与开发板,从Camera获取视频,基于yolov5s模型对输入视频中的物体做实时检测,将推理结果信息使用imshow方式显示。 + 样例结构如下所示: ![输入图片说明](https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/samples-pic/EdgeAndRobotics/%E5%8D%95%E7%BA%BF%E7%A8%8B%E7%A4%BA%E4%BE%8B%E5%9B%BE%E7%89%87.png) @@ -33,11 +34,13 @@ cd EdgeAndRobotics-master/AIApplication/YOLOV5USBCamera ``` -#### 准备环境 +#### 执行准备 + +1. 确认已安装带桌面的镜像且HDMI连接的屏幕正常显示 -1. 以HwHiAiUser用户登录开发板。 +2. 以HwHiAiUser用户登录开发板。 -2. 设置环境变量。 +3. 设置环境变量。 ``` # 配置程序编译依赖的头文件与库文件路径 @@ -45,7 +48,7 @@ export NPU_HOST_LIB=$DDK_PATH/runtime/lib64/stub ``` -3. 安装ACLLite库。 +4. 安装ACLLite库。 参考[ACLLite仓](https://gitee.com/ascend/ACLLite)安装ACLLite库。 @@ -54,22 +57,26 @@ 1. 以HwHiAiUser用户登录开发板,切换到当前样例目录。 2. 获取PyTorch框架的Yolov5模型(\*.onnx),并转换为昇腾AI处理器能识别的模型(\*.om)。 - - ``` - # 为了方便下载,在这里直接给出原始模型下载及模型转换命令,可以直接拷贝执行。 - cd model - wget https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/003_Atc_Models/yolov5s/yolov5s.onnx --no-check-certificate - wget https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/003_Atc_Models/yolov5s/aipp.cfg --no-check-certificate - atc --model=yolov5s.onnx --framework=5 --output=yolov5s --input_shape="images:1,3,640,640" --soc_version=Ascend310B4 --insert_op_conf=aipp.cfg - ``` - - atc命令中各参数的解释如下,详细约束说明请参见[《ATC模型转换指南》](https://hiascend.com/document/redirect/CannCommunityAtc)。 - - - --model:ResNet-50网络的模型文件的路径。 - - --framework:原始框架类型。5表示ONNX。 - - --output:yolov5s.om模型文件的路径。请注意,记录保存该om模型文件的路径,后续开发应用时需要使用。 - - --input\_shape:模型输入数据的shape。 - - --soc\_version:昇腾AI处理器的版本。 + - 当设备内存**小于8G**时,可设置如下两个环境变量减少atc模型转换过程中使用的进程数,减小内存占用。 + ``` + export TE_PARALLEL_COMPILER=1 + export MAX_COMPILE_CORE_NUMBER=1 + ``` + - 为了方便下载,在这里直接给出原始模型下载及模型转换命令,可以直接拷贝执行。 + ``` + cd model + wget https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/003_Atc_Models/yolov5s/yolov5s.onnx --no-check-certificate + wget https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/003_Atc_Models/yolov5s/aipp.cfg --no-check-certificate + atc --model=yolov5s.onnx --framework=5 --output=yolov5s --input_shape="images:1,3,640,640" --soc_version=Ascend310B4 --insert_op_conf=aipp.cfg + ``` + + atc命令中各参数的解释如下,详细约束说明请参见[《ATC模型转换指南》](https://hiascend.com/document/redirect/CannCommunityAtc)。 + + - --model:ResNet-50网络的模型文件的路径。 + - --framework:原始框架类型。5表示ONNX。 + - --output:yolov5s.om模型文件的路径。请注意,记录保存该om模型文件的路径,后续开发应用时需要使用。 + - --input\_shape:模型输入数据的shape。 + - --soc\_version:昇腾AI处理器的版本。 3. 编译样例源码。