Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Yolov5 classification model support #1082

Merged
merged 17 commits into from
Aug 30, 2022
Merged

Conversation

xiang-wuu
Copy link
Contributor

@xiang-wuu xiang-wuu commented Aug 22, 2022

This PR will update the Yolov5 TRT network to support Yolov5 classification model serialization and inference as per the recent yolov5-v6.2, this PR can be linked to issue #1077, and cover below tasks.

  • Update gen_wts.py script to support Yolov5 classification model export.
  • Update build_engine TRT network definition to initially support Yolov5s model
  • Test the Yolov5s based classification model serialization and infer testing.
  • Update build_engine TRT network definition to support all models
  • Validate the infer results of PyTorch with TRT

@wang-xinyu
Copy link
Owner

@xiang-wuu Awesome, looking forward to your implementation.

@wang-xinyu
Copy link
Owner

@xiang-wuu Hi, for classification model, can you write a separate .cpp file with main() function, and build another executable file? That will simplify the logic.

yolov5/yolov5.cpp Outdated Show resolved Hide resolved
@xiang-wuu
Copy link
Contributor Author

xiang-wuu commented Aug 24, 2022

  • Update build_engine TRT network definition to support all models

As the p6 scale models are not provided officially for Yolov5 classification models, so this can be done afterwards once the support is added. The normal scale models are working fine.

…, hence hardcoded value provided to support all model varients
@xiang-wuu
Copy link
Contributor Author

xiang-wuu commented Aug 25, 2022

Evaluation Metrics

Model Size Framework/IE Architecture(GPU/CPU) Precision Accuracy(Top-1) F1-score Latency
YOLOv5s-cls 224 TensorRT Nvidia GTX 1060 FP32 69.892 0.6952 1.40 ms
YOLOv5s-cls 224 PyTorch Nvidia GTX 1060 FP32 71.724 0.7136 3.07 ms
  • Validate the infer results of PyTorch with TRT

As per the last subtask, the model is been inferred separately using PyTorch and TRT over 50K validation dataset from imagenet, also the time complexity is averaged over 5K dry runs for both model implementations. The slight reduction in accuracy numbers of TRT model could possibly caused due to pre-processing or post-processing implementations.

@sctrueew
Copy link

sctrueew commented Aug 26, 2022

@wang-xinyu Hi,

I appreciate your implementation. In C++, how do I display className and prob after the infer? In the Python file, there is an example, but I haven't seen it in the C++ file.

Should I change these lines to:

`for (int b = 0; b < fcount; b++) {
auto & res = batch_res[b];
cv::Mat img = imgs_buffer[b];
for (size_t j = 0; j < res.size(); j++) {
cv::Rect r = get_rect(img, res[j].bbox);
cv::rectangle(img, r, cv::Scalar(0x27, 0xC1, 0x36), 2);
cv::putText(img, std::to_string((int) res[j].class_id), cv::Point(r.x, r.y - 1), cv::FONT_HERSHEY_PLAIN, 1.2, cv::Scalar(0xFF, 0xFF, 0xFF), 2);
}
cv::imwrite("_" + file_names[f - fcount + 1 + b], img);

}`

To:
vector classes;
`for (int b = 0; b < fcount; b++) {
auto & res = batch_res[b];
cv::Mat img = imgs_buffer[b];
for (size_t j = 0; j < res.size(); j++) {
auto className = classes[res[j].class_id];
auto prob = res[j].prob;
}

}`

Copy link
Owner

@wang-xinyu wang-xinyu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot. I left few comments.

yolov5/CMakeLists.txt Outdated Show resolved Hide resolved
yolov5/gen_wts.py Outdated Show resolved Hide resolved
yolov5/yolov5.cpp Outdated Show resolved Hide resolved
yolov5/yolov5_cls.cpp Show resolved Hide resolved
yolov5/yolov5_cls.cpp Outdated Show resolved Hide resolved
yolov5/yolov5_trt.py Outdated Show resolved Hide resolved
@xiang-wuu
Copy link
Contributor Author

@wang-xinyu Hi,

I appreciate your implementation. In C++, how do I display className and prob after the infer? In the Python file, there is an example, but I haven't seen it in the C++ file.

Should I change these lines to:

`for (int b = 0; b < fcount; b++) { auto & res = batch_res[b]; cv::Mat img = imgs_buffer[b]; for (size_t j = 0; j < res.size(); j++) { cv::Rect r = get_rect(img, res[j].bbox); cv::rectangle(img, r, cv::Scalar(0x27, 0xC1, 0x36), 2); cv::putText(img, std::to_string((int) res[j].class_id), cv::Point(r.x, r.y - 1), cv::FONT_HERSHEY_PLAIN, 1.2, cv::Scalar(0xFF, 0xFF, 0xFF), 2); } cv::imwrite("_" + file_names[f - fcount + 1 + b], img);

}`

To: vector classes; `for (int b = 0; b < fcount; b++) { auto & res = batch_res[b]; cv::Mat img = imgs_buffer[b]; for (size_t j = 0; j < res.size(); j++) { auto className = classes[res[j].class_id]; auto prob = res[j].prob; }

}`

de-serialization is not handled in the CPP code, it can be easily implemented from the python infer script.

@xiang-wuu
Copy link
Contributor Author

@wang-xinyu 根据您的建议,所有更改都已完成

@wang-xinyu
Copy link
Owner

@xiang-wuu 我的意思是,不要修改yolov5.cpp和yolov5_trt.py这两个文件,现在PR里面包含了这两个文件的一点改动。

@xiang-wuu
Copy link
Contributor Author

@wang-xinyu both the files yolov5.cpp and yolov5_trt.py are reverted back to the original state, there still might be some formatting changes visible in git diff, kindly ignore them!

@wang-xinyu
Copy link
Owner

@xiang-wuu Even format differences, can you revert them? Some lines don't need line-break, but line-breaks are applied. Especially in yolov5_trt.py.

@xiang-wuu
Copy link
Contributor Author

@wang-xinyu as you mention to revert the format changes in yolov5_trt.py file it would be difficult to revert back to prior commit state for single file, however removing all formatting changes back to original state won't revert the git blame authorship to the previous commit author. If you still want me to do the changes manually then let me know.

@wang-xinyu
Copy link
Owner

@xiang-wuu Can you please download the yolov5_trt.py from master branch and overwrite it to your current yolov5_trt.py? That will be easier. No need to consider the git commit state.

@xiang-wuu
Copy link
Contributor Author

@wang-xinyu Reverted back to prior commit.

@wang-xinyu
Copy link
Owner

@xiang-wuu Thanks.

@wang-xinyu
Copy link
Owner

@xiang-wuu So you are using v6.2, right? Have you tested the v6.2 detection model with your branch?

@wang-xinyu wang-xinyu merged commit a772e46 into wang-xinyu:master Aug 30, 2022
@sctrueew
Copy link

@wang-xinyu Hi,

I'd like to print the classification result in C++ but the result it's not correct:

`

	auto start = std::chrono::system_clock::now();
	doInference(*context, stream, (void**)buffers, prob, BATCH_SIZE);
	auto end = std::chrono::system_clock::now();
	std::cout << "inference time: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;
	float maxp = 0;
	int index = 0;
	for (int b = 0; b < fcount; b++) {
		for (int j = 0; j < 1000; ++j)
		{
			float p = prob[b * OUTPUT_SIZE + j];
			if (p > maxp)
			{
				maxp = p;
				index = j;
			}
		}
	}
	std::cout << "out index: " << index << " prob: " << maxp << std::endl;

`

@sctrueew
Copy link

I changed my code to

`

	std::unordered_map<float, int> prob_index;
	for (int j = 0; j < OUTPUT_SIZE; ++j) {
		prob_index[prob[j]] = j;
	}
	std::sort(prob, prob + OUTPUT_SIZE, [](int x, int y) { return x > y; });
	for (int a = 0; a < 10; ++a) {
		int label = prob_index[prob[a]];
		auto pr = prob[a];
		std::string s = std::to_string(pr);
		std::cout << "topk label: " << label << std::endl;
		std::cout << "topk prob: " << s << std::endl;
	}

`

but the result always are:

inference time: 12ms
topk label: 623
topk prob: 4.086990
topk label: 844
topk prob: 3.013781
topk label: 499
topk prob: 3.963979
topk label: 769
topk prob: 3.052796
topk label: 699
topk prob: 3.400196
topk label: 596
topk prob: 3.919277
topk label: 902
topk prob: 3.024654
topk label: 551
topk prob: 3.231964
topk label: 846
topk prob: 3.721910
topk label: 763
topk prob: 3.045218

Would you be able to give me some tips on how to resolve this?

@wang-xinyu
Copy link
Owner

@sctrueew Have you try to use the .py to run inference.

@sctrueew
Copy link

@wang-xinyu No, I haven't. It is my goal to use C++.

@xiang-wuu
Copy link
Contributor Author

@xiang-wuu So you are using v6.2, right? Have you tested the v6.2 detection model with your branch?

@wang-xinyu as per the official release notes of v6.2 there is no significant architecture changes for detection models since release v6.0 hence detection models from v6.2 works here without any issue.

@xiang-wuu
Copy link
Contributor Author

@wang-xinyu also let me know , do you want me to update the README file for this PR specific changes, then i can raise separate PR for the same.

@wang-xinyu
Copy link
Owner

@xiang-wuu If you can verify the detection model on v6.2 branch, that will be great. We can update the readme after that.
If you are not interested in that, I will verify it later, and also update readme later.

@xiang-wuu
Copy link
Contributor Author

@xiang-wuu If you can verify the detection model on v6.2 branch, that will be great. We can update the readme after that. If you are not interested in that, I will verify it later, and also update readme later.

As i mentioned earlier, i verified that and it's working fine.

@sctrueew
Copy link

sctrueew commented Sep 5, 2022

@xiang-wuu,
I couldn't find any solution. Could you please give us some tips to get results in C++?

@wang-xinyu
Copy link
Owner

@sctrueew @xiang-wuu I have updated the cpp code, the c++ inference is working now, can you check?

@sctrueew
Copy link

sctrueew commented Sep 6, 2022

@wang-xinyu Thanks. I've updated the code to the latest version and tested it but I don't know how to display the result after doInference.

I'm using this to display: Is it correct?

`

std::unordered_map<float, int> prob_index;

	for (int j = 0; j < OUTPUT_SIZE; ++j) {
		prob_index[prob[j]] = j;
	}
	std::sort(prob, prob + OUTPUT_SIZE, [](int x, int y) { return x > y; });
	for (int a = 0; a < 10; ++a) {
		int label = prob_index[prob[a]];
		auto pr = prob[a];
		std::string s = std::to_string(pr);
		std::cout << "topk label: " << label << std::endl;
		std::cout << "topk prob: " << s << std::endl;
	}`

@wang-xinyu
Copy link
Owner

@sctrueew Cpp postprocessing is also added, please check.

@sctrueew
Copy link

sctrueew commented Sep 7, 2022

@wang-xinyu Thanks for the implementation. I've tested but the result is always this for all images:

../giraffe.jpg
letter opener, paper knife, paperknife 0.0260404
cleaver, meat cleaver, chopper 0.0230263
hatchet 0.0220196

wang-xinyu pushed a commit that referenced this pull request Dec 16, 2022
* updated gen_wts script to support yolov5 classfication model export

* updated yolov5-s architecture to support classification head.

* updated yolov5_trt infer script to support yolov5 classification model alongwith existing detection model.

* added imagenet_classes file to load list of 1k classes required for the infer script.

* final conv block doesn't require dynamic scale factor for out channel, hence hardcoded value provided to support all model varients

* yolov5.cpp reverted back to original state, with explicit code changes

* python infer script reverted back to prior state, with explicit code changes

* seperate cpp file added for yolov5 classification task

* cmake updated for yolo5 classification file

* seperate python infer script for classification task

* cmake updated by replacing cuda_add_executable with add_executable

* default value added to the type argument

* post-processing removed from yolov5 clasisifcation module

* pre-processing for yolov5 classification inferencing

* classification macro removed from the original yolov5 detection cpp file

* reverted some extremely minor formatting changes.

* reverted back to prior state by removing all formatting changes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants