Link to this sectionYOLOv7: مجموعة الحلول المجانية القابلة للتدريب#
يعد YOLOv7، الذي تم إصداره في يوليو 2022، تطوراً كبيراً في اكتشاف الأشياء في الوقت الفعلي وقت إصداره. حقق نسبة 56.8% AP على وحدة معالجة الرسومات V100، واضعاً معايير جديدة عند تقديمه. تفوق YOLOv7 على كاشفات الأشياء المعاصرة مثل YOLOR وYOLOX وScaled-YOLOv4 وYOLOv5 من حيث السرعة والدقة. تم تدريب النموذج على مجموعة بيانات MS COCO من الصفر دون استخدام أي مجموعات بيانات أخرى أو أوزان مدربة مسبقاً. الكود المصدري لـ YOLOv7 متاح على GitHub. لاحظ أن النماذج الأحدث مثل YOLO11 وYOLO26 قد حققت منذ ذلك الحين دقة أعلى مع كفاءة محسنة.

Link to this sectionمقارنة كاشفات الأشياء الحديثة (SOTA)#
من النتائج في جدول مقارنة YOLO، نعلم أن الطريقة المقترحة تمتلك أفضل مقايضة بين السرعة والدقة بشكل شامل. إذا قارنا YOLOv7-tiny-SiLU مع YOLOv5-N (r6.1)، فإن طريقتنا أسرع بـ 127 إطاراً في الثانية وأكثر دقة بنسبة 10.7% من حيث AP. بالإضافة إلى ذلك، يمتلك YOLOv7 نسبة 51.4% AP بمعدل إطارات 161 إطاراً في الثانية، بينما يمتلك PPYOLOE-L بنفس نسبة AP معدل إطارات 78 إطاراً في الثانية فقط. من حيث استخدام المعلمات، يعد YOLOv7 أقل بنسبة 41% من PPYOLOE-L.
إذا قارنا YOLOv7-X بسرعة استنتاج تبلغ 114 إطاراً في الثانية بـ YOLOv5-L (r6.1) بسرعة استنتاج تبلغ 99 إطاراً في الثانية، يمكن لـ YOLOv7-X تحسين AP بنسبة 3.9%. إذا تمت مقارنة YOLOv7-X بـ YOLOv5-X (r6.1) من مقياس مشابه، فإن سرعة استنتاج YOLOv7-X أسرع بـ 31 إطاراً في الثانية. بالإضافة إلى ذلك، من حيث كمية المعلمات والحوسبة، يقلل YOLOv7-X من المعلمات بنسبة 22% والحوسبة بنسبة 8% مقارنة بـ YOLOv5-X (r6.1)، ولكنه يحسن AP بنسبة 2.2% (المصدر).
| النموذج | البارامترات (M) | FLOPs (G) | الحجم (بكسل) | FPS | APاختبار / تحقق 50-95 | APاختبار 50 | APاختبار 75 | APاختبار S | APاختبار M | APاختبار L |
|---|---|---|---|---|---|---|---|---|---|---|
| YOLOX-S | 9.0 | 26.8 | 640 | 102 | 40.5% / 40.5% | - | - | - | - | - |
| YOLOX-M | 25.3 | 73.8 | 640 | 81 | 47.2% / 46.9% | - | - | - | - | - |
| YOLOX-L | 54.2 | 155.6 | 640 | 69 | 50.1% / 49.7% | - | - | - | - | - |
| YOLOX-X | 99.1 | 281.9 | 640 | 58 | 51.5% / 51.1% | - | - | - | - | - |
| PPYOLOE-S | 7.9 | 17.4 | 640 | 208 | 43.1% / 42.7% | 60.5% | 46.6% | 23.2% | 46.4% | 56.9% |
| PPYOLOE-M | 23.4 | 49.9 | 640 | 123 | 48.9% / 48.6% | 66.5% | 53.0% | 28.6% | 52.9% | 63.8% |
| PPYOLOE-L | 52.2 | 110.1 | 640 | 78 | 51.4% / 50.9% | 68.9% | 55.6% | 31.4% | 55.3% | 66.1% |
| PPYOLOE-X | 98.4 | 206.6 | 640 | 45 | 52.2% / 51.9% | 69.9% | 56.5% | 33.3% | 56.3% | 66.4% |
| YOLOv5-N (r6.1) | 1.9 | 4.5 | 640 | 159 | - / 28.0% | - | - | - | - | - |
| YOLOv5-S (r6.1) | 7.2 | 16.5 | 640 | 156 | - / 37.4% | - | - | - | - | - |
| YOLOv5-M (r6.1) | 21.2 | 49.0 | 640 | 122 | - / 45.4% | - | - | - | - | - |
| YOLOv5-L (r6.1) | 46.5 | 109.1 | 640 | 99 | - / 49.0% | - | - | - | - | - |
| YOLOv5-X (r6.1) | 86.7 | 205.7 | 640 | 83 | - / 50.7% | - | - | - | - | - |
| YOLOR-CSP | 52.9 | 120.4 | 640 | 106 | 51.1% / 50.8% | 69.6% | 55.7% | 31.7% | 55.3% | 64.7% |
| YOLOR-CSP-X | 96.9 | 226.8 | 640 | 87 | 53.0% / 52.7% | 71.4% | 57.9% | 33.7% | 57.1% | 66.8% |
| YOLOv7-tiny-SiLU | 6.2 | 13.8 | 640 | 286 | 38.7% / 38.7% | 56.7% | 41.7% | 18.8% | 42.4% | 51.9% |
| YOLOv7 | 36.9 | 104.7 | 640 | 161 | 51.4% / 51.2% | 69.7% | 55.9% | 31.8% | 55.5% | 65.0% |
| YOLOv7-X | 71.3 | 189.9 | 640 | 114 | 53.1% / 52.9% | 71.2% | 57.8% | 33.8% | 57.1% | 67.4% |
| YOLOv5-N6 (r6.1) | 3.2 | 18.4 | 1280 | 123 | / 36.0% | - | - | - | - | - |
| YOLOv5-S6 (r6.1) | 12.6 | 67.2 | 1280 | 122 | / 44.8% | - | - | - | - | - |
| YOLOv5-M6 (r6.1) | 35.7 | 200.0 | 1280 | 90 | / 51.3% | - | - | - | - | - |
| YOLOv5-L6 (r6.1) | 76.8 | 445.6 | 1280 | 63 | / 53.7% | - | - | - | - | - |
| YOLOv5-X6 (r6.1) | 140.7 | 839.2 | 1280 | 38 | / 55.0% | - | - | - | - | - |
| YOLOR-P6 | 37.2 | 325.6 | 1280 | 76 | 53.9% / 53.5% | 71.4% | 58.9% | 36.1% | 57.7% | 65.6% |
| YOLOR-W6 | 79.8 | 453.2 | 1280 | 66 | 55.2% / 54.8% | 72.7% | 60.5% | 37.7% | 59.1% | 67.1% |
| YOLOR-E6 | 115.8 | 683.2 | 1280 | 45 | 55.8% / 55.7% | 73.4% | 61.1% | 38.4% | 59.7% | 67.7% |
| YOLOR-D6 | 151.7 | 935.6 | 1280 | 34 | 56.5% / 56.1% | 74.1% | 61.9% | 38.9% | 60.4% | 68.7% |
| YOLOv7-W6 | 70.4 | 360.0 | 1280 | 84 | 54.9% / 54.6% | 72.6% | 60.1% | 37.3% | 58.7% | 67.1% |
| YOLOv7-E6 | 97.2 | 515.2 | 1280 | 56 | 56.0% / 55.9% | 73.5% | 61.2% | 38.0% | 59.9% | 68.4% |
| YOLOv7-D6 | 154.7 | 806.8 | 1280 | 44 | 56.6% / 56.3% | 74.0% | 61.8% | 38.8% | 60.1% | 69.5% |
| YOLOv7-E6E | 151.7 | 843.2 | 1280 | 36 | 56.8% / 56.8% | 74.4% | 62.1% | 39.3% | 60.5% | 69.0% |
Link to this sectionنظرة عامة#
يعد اكتشاف الأشياء في الوقت الفعلي مكوناً مهماً في العديد من أنظمة الرؤية الحاسوبية، بما في ذلك تتبع الأشياء المتعددة، والقيادة الذاتية، والروبوتات، وتحليل الصور الطبية. في السنوات الأخيرة، ركز تطوير اكتشاف الأشياء في الوقت الفعلي على تصميم بنيات فعالة وتحسين سرعة الاستدلال لمختلف وحدات المعالجة المركزية (CPUs)، ووحدات معالجة الرسومات (GPUs)، ووحدات المعالجة العصبية (NPUs). يدعم YOLOv7 كلاً من أجهزة GPU المحمولة وأجهزة GPU، من الحافة إلى السحابة.
على عكس كاشفات الأشياء التقليدية في الوقت الفعلي التي تركز على تحسين البنية، يقدم YOLOv7 تركيزاً على تحسين عملية التدريب. يشمل ذلك وحدات وطرق تحسين مصممة لتحسين دقة اكتشاف الأشياء دون زيادة تكلفة الاستدلال، وهو مفهوم يُعرف باسم "مجموعة المزايا المجانية القابلة للتدريب" (trainable bag-of-freebies).
Link to this sectionالميزات الرئيسية#
يقدم YOLOv7 العديد من الميزات الرئيسية:
-
إعادة تهيئة النموذج (Model Re-parameterization): يقترح YOLOv7 نموذجاً معاد تهيئته مخططاً له، وهي استراتيجية قابلة للتطبيق على الطبقات في شبكات مختلفة باستخدام مفهوم مسار انتشار التدرج.
-
تعيين التسميات الديناميكي (Dynamic Label Assignment): يطرح تدريب النموذج بطبقات إخراج متعددة مشكلة جديدة: "كيف يتم تعيين أهداف ديناميكية لمخرجات الفروع المختلفة؟" لحل هذه المشكلة، يقدم YOLOv7 طريقة جديدة لتعيين التسميات تسمى تعيين التسميات الموجه بالقيادة من الخشن إلى الدقيق (coarse-to-fine lead guided label assignment).
-
التحجيم الموسع والمركب (Extended and Compound Scaling): يقترح YOLOv7 طرق "توسيع" و"تحجيم مركب" لكاشف الأشياء في الوقت الفعلي والتي يمكنها الاستفادة بفعالية من المعلمات والحسابات.
-
الكفاءة: يمكن للطريقة المقترحة من قبل YOLOv7 تقليل حوالي 40% من المعلمات و50% من الحسابات لكاشف الأشياء في الوقت الفعلي المتطور، وتتميز بسرعة استدلال أسرع ودقة اكتشاف أعلى.
Link to this sectionأمثلة الاستخدام#
لا تنشر Ultralytics أوزان yolov7.pt المدربة مسبقاً أو ملفات ultralytics/cfg/models/v7/ بصيغة YAML، كما أن التدريب والاستدلال الأصليين لـ PyTorch الخاص بـ YOLOv7 غير مدعومين بواسطة حزمة Ultralytics Python. ومع ذلك، يمكنك إحضار نقطة فحص (checkpoint) لـ YOLOv7 تم تدريبها في مستودع YOLOv7 الرئيسي إلى Ultralytics عن طريق تصديرها إلى ONNX أو TensorRT، كما هو موضح أدناه.
Link to this sectionتصدير ONNX#
لاستخدام نموذج YOLOv7 ONNX مع Ultralytics:
-
(اختياري) قم بتثبيت Ultralytics وتصدير نموذج ONNX للحصول على التبعيات المطلوبة مثبتة تلقائياً:
pip install ultralytics yolo export model=yolo26n.pt format=onnx -
قم بتصدير نموذج YOLOv7 المطلوب باستخدام أداة التصدير في مستودع YOLOv7:
git clone https://github.com/WongKinYiu/yolov7 cd yolov7 python export.py --weights yolov7-tiny.pt --grid --end2end --simplify --topk-all 100 --iou-thres 0.65 --conf-thres 0.35 --img-size 640 640 --max-wh 640 -
قم بتعديل رسم بياني لنموذج ONNX ليكون متوافقاً مع Ultralytics باستخدام البرنامج النصي التالي:
import numpy as np import onnx from onnx import helper, numpy_helper # Load the ONNX model model_path = "yolov7/yolov7-tiny.onnx" # Replace with your model path model = onnx.load(model_path) graph = model.graph # Fix input shape to batch size 1 input_shape = graph.input[0].type.tensor_type.shape input_shape.dim[0].dim_value = 1 # Define the output of the original model original_output_name = graph.output[0].name # Create slicing nodes sliced_output_name = f"{original_output_name}_sliced" # Define initializers for slicing (remove the first value) start = numpy_helper.from_array(np.array([1], dtype=np.int64), name="slice_start") end = numpy_helper.from_array(np.array([7], dtype=np.int64), name="slice_end") axes = numpy_helper.from_array(np.array([1], dtype=np.int64), name="slice_axes") steps = numpy_helper.from_array(np.array([1], dtype=np.int64), name="slice_steps") graph.initializer.extend([start, end, axes, steps]) slice_node = helper.make_node( "Slice", inputs=[original_output_name, "slice_start", "slice_end", "slice_axes", "slice_steps"], outputs=[sliced_output_name], name="SliceNode", ) graph.node.append(slice_node) # Define segment slicing seg1_start = numpy_helper.from_array(np.array([0], dtype=np.int64), name="seg1_start") seg1_end = numpy_helper.from_array(np.array([4], dtype=np.int64), name="seg1_end") seg2_start = numpy_helper.from_array(np.array([4], dtype=np.int64), name="seg2_start") seg2_end = numpy_helper.from_array(np.array([5], dtype=np.int64), name="seg2_end") seg3_start = numpy_helper.from_array(np.array([5], dtype=np.int64), name="seg3_start") seg3_end = numpy_helper.from_array(np.array([6], dtype=np.int64), name="seg3_end") graph.initializer.extend([seg1_start, seg1_end, seg2_start, seg2_end, seg3_start, seg3_end]) # Create intermediate tensors for segments segment_1_name = f"{sliced_output_name}_segment1" segment_2_name = f"{sliced_output_name}_segment2" segment_3_name = f"{sliced_output_name}_segment3" # Add segment slicing nodes graph.node.extend( [ helper.make_node( "Slice", inputs=[sliced_output_name, "seg1_start", "seg1_end", "slice_axes", "slice_steps"], outputs=[segment_1_name], name="SliceSegment1", ), helper.make_node( "Slice", inputs=[sliced_output_name, "seg2_start", "seg2_end", "slice_axes", "slice_steps"], outputs=[segment_2_name], name="SliceSegment2", ), helper.make_node( "Slice", inputs=[sliced_output_name, "seg3_start", "seg3_end", "slice_axes", "slice_steps"], outputs=[segment_3_name], name="SliceSegment3", ), ] ) # Concatenate the segments concat_output_name = f"{sliced_output_name}_concat" concat_node = helper.make_node( "Concat", inputs=[segment_1_name, segment_3_name, segment_2_name], outputs=[concat_output_name], axis=1, name="ConcatSwapped", ) graph.node.append(concat_node) # Reshape to [1, -1, 6] reshape_shape = numpy_helper.from_array(np.array([1, -1, 6], dtype=np.int64), name="reshape_shape") graph.initializer.append(reshape_shape) final_output_name = f"{concat_output_name}_batched" reshape_node = helper.make_node( "Reshape", inputs=[concat_output_name, "reshape_shape"], outputs=[final_output_name], name="AddBatchDimension", ) graph.node.append(reshape_node) # Get the shape of the reshaped tensor shape_node_name = f"{final_output_name}_shape" shape_node = helper.make_node( "Shape", inputs=[final_output_name], outputs=[shape_node_name], name="GetShapeDim", ) graph.node.append(shape_node) # Extract the second dimension dim_1_index = numpy_helper.from_array(np.array([1], dtype=np.int64), name="dim_1_index") graph.initializer.append(dim_1_index) second_dim_name = f"{final_output_name}_dim1" gather_node = helper.make_node( "Gather", inputs=[shape_node_name, "dim_1_index"], outputs=[second_dim_name], name="GatherSecondDim", ) graph.node.append(gather_node) # Subtract from 100 to determine how many values to pad target_size = numpy_helper.from_array(np.array([100], dtype=np.int64), name="target_size") graph.initializer.append(target_size) pad_size_name = f"{second_dim_name}_padsize" sub_node = helper.make_node( "Sub", inputs=["target_size", second_dim_name], outputs=[pad_size_name], name="CalculatePadSize", ) graph.node.append(sub_node) # Build the [2, 3] pad array: # 1st row -> [0, 0, 0] (no padding at the start of any dim) # 2nd row -> [0, pad_size, 0] (pad only at the end of the second dim) pad_starts = numpy_helper.from_array(np.array([0, 0, 0], dtype=np.int64), name="pad_starts") graph.initializer.append(pad_starts) zero_scalar = numpy_helper.from_array(np.array([0], dtype=np.int64), name="zero_scalar") graph.initializer.append(zero_scalar) pad_ends_name = "pad_ends" concat_pad_ends_node = helper.make_node( "Concat", inputs=["zero_scalar", pad_size_name, "zero_scalar"], outputs=[pad_ends_name], axis=0, name="ConcatPadEnds", ) graph.node.append(concat_pad_ends_node) pad_values_name = "pad_values" concat_pad_node = helper.make_node( "Concat", inputs=["pad_starts", pad_ends_name], outputs=[pad_values_name], axis=0, name="ConcatPadStartsEnds", ) graph.node.append(concat_pad_node) # Create Pad operator to pad with zeros pad_output_name = f"{final_output_name}_padded" pad_constant_value = numpy_helper.from_array( np.array([0.0], dtype=np.float32), name="pad_constant_value", ) graph.initializer.append(pad_constant_value) pad_node = helper.make_node( "Pad", inputs=[final_output_name, pad_values_name, "pad_constant_value"], outputs=[pad_output_name], mode="constant", name="PadToFixedSize", ) graph.node.append(pad_node) # Update the graph's final output to [1, 100, 6] new_output_type = onnx.helper.make_tensor_type_proto( elem_type=graph.output[0].type.tensor_type.elem_type, shape=[1, 100, 6] ) new_output = onnx.helper.make_value_info(name=pad_output_name, type_proto=new_output_type) # Replace the old output with the new one graph.output.pop() graph.output.extend([new_output]) # Save the modified model onnx.save(model, "yolov7-ultralytics.onnx") -
يمكنك بعد ذلك تحميل نموذج ONNX المعدل وتشغيل الاستدلال به في Ultralytics بشكل طبيعي:
from ultralytics import ASSETS, YOLO model = YOLO("yolov7-ultralytics.onnx", task="detect") results = model(ASSETS / "bus.jpg")
Link to this sectionتصدير TensorRT#
-
اتبع الخطوات 1-2 في قسم تصدير ONNX.
-
قم بتثبيت حزمة
TensorRTلـ Python:pip install tensorrt -
قم بتشغيل البرنامج النصي التالي لتحويل نموذج ONNX المعدل إلى محرك TensorRT:
from ultralytics.utils.export import export_engine export_engine("yolov7-ultralytics.onnx", half=True) -
تحميل وتشغيل النموذج في Ultralytics:
from ultralytics import ASSETS, YOLO model = YOLO("yolov7-ultralytics.engine", task="detect") results = model(ASSETS / "bus.jpg")
Link to this sectionالاقتباسات والشكر#
نود أن نشكر مؤلفي YOLOv7 على مساهماتهم الكبيرة في مجال اكتشاف الأشياء في الوقت الفعلي:
@inproceedings{wang2023yolov7,
title={YOLOv7: Trainable Bag-of-Freebies Sets New State-of-the-Art for Real-Time Object Detectors},
author={Wang, Chien-Yao and Bochkovskiy, Alexey and Liao, Hong-Yuan Mark},
booktitle={Proceedings of the IEEE/CVF conference on Computer Vision and Pattern Recognition (CVPR)},
pages={7464--7475},
year={2023}
}تم نشر ورقة YOLOv7 الرسمية في CVF 2023 Open Access، مع نسخة أولية على arXiv. جعل المؤلفون عملهم متاحاً للجمهور، ويمكن الوصول إلى قاعدة التعليمات البرمجية على GitHub. نحن نقدر جهودهم في تطوير المجال وجعل عملهم متاحاً للمجتمع الأوسع.
Link to this sectionالأسئلة الشائعة#
Link to this sectionما هو YOLOv7 ولماذا يعتبر طفرة في اكتشاف الأشياء في الوقت الفعلي؟#
YOLOv7، الذي تم إصداره في يوليو 2022، كان نموذجاً مهماً لاكتشاف الأشياء في الوقت الفعلي حقق سرعة ودقة ممتازتين وقت إصداره. لقد تفوق على النماذج المعاصرة مثل YOLOX، وYOLOv5، وPPYOLOE في كل من استخدام المعلمات وسرعة الاستدلال. تشمل الميزات المميزة لـ YOLOv7 إعادة تهيئة النموذج وتعيين التسميات الديناميكي، اللذين يعملان على تحسين أدائه دون زيادة تكاليف الاستدلال. لمزيد من التفاصيل الفنية حول بنيته ومقاييس المقارنة مع كاشفات الأشياء المتطورة الأخرى، راجع ورقة YOLOv7.
Link to this sectionكيف يتحسن YOLOv7 مقارنة بنماذج YOLO السابقة مثل YOLOv4 وYOLOv5؟#
يقدم YOLOv7 العديد من الابتكارات، بما في ذلك إعادة تهيئة النموذج وتعيين التسميات الديناميكي، التي تعزز عملية التدريب وتحسن دقة الاستدلال. مقارنة بـ YOLOv5، يعزز YOLOv7 السرعة والدقة بشكل كبير. على سبيل المثال، يحسن YOLOv7-X الدقة بنسبة 2.2% ويقلل المعلمات بنسبة 22% مقارنة بـ YOLOv5-X. يمكن العثور على مقارنات تفصيلية في جدول الأداء مقارنة YOLOv7 مع كاشفات الأشياء المتطورة.
Link to this sectionهل يمكنني استخدام YOLOv7 مع أدوات ومنصات Ultralytics؟#
حتى الآن، تدعم Ultralytics فقط استدلال YOLOv7 ONNX وTensorRT. لتشغيل إصدار YOLOv7 الذي تم تصديره إلى ONNX وTensorRT مع Ultralytics، تحقق من قسم أمثلة الاستخدام.
Link to this sectionكيف أقوم بتدريب نموذج YOLOv7 مخصص باستخدام مجموعة البيانات الخاصة بي؟#
لتثبيت وتدريب نموذج YOLOv7 مخصص، اتبع الخطوات التالية:
-
استنسخ مستودع YOLOv7:
git clone https://github.com/WongKinYiu/yolov7 -
انتقل إلى الدليل المستنسخ وقم بتثبيت التبعيات:
cd yolov7 pip install -r requirements.txt -
قم بإعداد مجموعة البيانات الخاصة بك وتهيئة معلمات النموذج وفقاً لـ تعليمات الاستخدام المقدمة في المستودع. لمزيد من التوجيه، قم بزيارة مستودع YOLOv7 على GitHub للحصول على أحدث المعلومات والتحديثات.
-
بعد التدريب، يمكنك تصدير النموذج إلى ONNX أو TensorRT للاستخدام في Ultralytics كما هو موضح في أمثلة الاستخدام.
Link to this sectionما هي الميزات والتحسينات الرئيسية التي تم إدخالها في YOLOv7؟#
يقدم YOLOv7 العديد من الميزات الرئيسية التي تحدث ثورة في اكتشاف الأشياء في الوقت الفعلي:
- إعادة تهيئة النموذج: يعزز أداء النموذج من خلال تحسين مسارات انتشار التدرج.
- تعيين التسميات الديناميكي: يستخدم طريقة موجهة بالقيادة من الخشن إلى الدقيق لتعيين أهداف ديناميكية للمخرجات عبر فروع مختلفة، مما يحسن الدقة.
- التحجيم الموسع والمركب: يستخدم بكفاءة المعلمات والحسابات لتوسيع نطاق النموذج لمختلف التطبيقات في الوقت الفعلي.
- الكفاءة: يقلل عدد المعلمات بنسبة 40% والحسابات بنسبة 50% مقارنة بالنماذج المتطورة الأخرى مع تحقيق سرعات استدلال أسرع.
لمزيد من التفاصيل حول هذه الميزات، راجع قسم نظرة عامة على YOLOv7.