You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TensorFlow Object Detection API中同时使用两个检测模型

Solution: Combine SSD MobileNet (COCO) and Custom Faster RCNN Detections

Great question! To detect both the 90 COCO classes and your custom objects in a single workflow, you'll need to load both models, run inference with each, combine their results (making sure class IDs don't overlap), and visualize everything together. Here's a complete, working code snippet to do that:

Step-by-Step Code Implementation

First, ensure you have the TensorFlow Object Detection API utilities (like label_map_util and visualization_utils) available in your environment. Then follow this code:

1. Import Required Libraries

import tensorflow as tf
import numpy as np
import cv2
from object_detection.utils import label_map_util
from object_detection.utils import visualization_utils as vis_util

2. Helper Functions

def load_detection_model(model_path):
    """Load a frozen TensorFlow detection graph"""
    detection_graph = tf.Graph()
    with detection_graph.as_default():
        od_graph_def = tf.compat.v1.GraphDef()
        with tf.io.gfile.GFile(model_path, 'rb') as fid:
            serialized_graph = fid.read()
            od_graph_def.ParseFromString(serialized_graph)
            tf.import_graph_def(od_graph_def, name='')
    return detection_graph

def run_inference(image, sess, image_tensor, boxes_tensor, scores_tensor, classes_tensor, num_detections_tensor, class_id_offset=0):
    """Run inference on an image and return filtered high-confidence detections"""
    # Expand dimensions to match model input shape [1, None, None, 3]
    image_expanded = np.expand_dims(image, axis=0)
    
    # Run inference
    (boxes, scores, classes, num) = sess.run(
        [boxes_tensor, scores_tensor, classes_tensor, num_detections_tensor],
        feed_dict={image_tensor: image_expanded})
    
    # Clean up output tensors by removing extra dimensions
    boxes = np.squeeze(boxes)
    scores = np.squeeze(scores)
    classes = np.squeeze(classes).astype(np.int32)
    
    # Offset class IDs to avoid overlap with COCO's 1-90 range
    if class_id_offset > 0:
        classes += class_id_offset
    
    # Filter out low-confidence detections (adjust threshold as needed)
    threshold = 0.5
    valid_mask = scores >= threshold
    return boxes[valid_mask], scores[valid_mask], classes[valid_mask]

3. Load Models and Label Maps

# --------------------------
# Update these paths to match your setup!
# --------------------------
SSD_MODEL_PATH = 'path/to/ssd_mobilenet_v1_coco_2017_11_17/frozen_inference_graph.pb'
FASTER_RCNN_MODEL_PATH = 'path/to/faster_rcnn_inception_v2_coco_2018_01_28/frozen_inference_graph.pb'
COCO_LABEL_MAP = 'object_detection/data/mscoco_label_map.pbtxt'
CUSTOM_LABEL_MAP = 'path/to/your/custom_label_map.pbtxt'
INPUT_IMAGE_PATH = 'path/to/your/input_image.jpg'
OUTPUT_IMAGE_PATH = 'path/to/save/output_image.jpg'

# Load both detection models
ssd_graph = load_detection_model(SSD_MODEL_PATH)
frcnn_graph = load_detection_model(FASTER_RCNN_MODEL_PATH)

# Create TensorFlow sessions for each model
ssd_sess = tf.compat.v1.Session(graph=ssd_graph)
frcnn_sess = tf.compat.v1.Session(graph=frcnn_graph)

# Get input/output tensors for SSD model
ssd_image_tensor = ssd_graph.get_tensor_by_name('image_tensor:0')
ssd_boxes = ssd_graph.get_tensor_by_name('detection_boxes:0')
ssd_scores = ssd_graph.get_tensor_by_name('detection_scores:0')
ssd_classes = ssd_graph.get_tensor_by_name('detection_classes:0')
ssd_num_detections = ssd_graph.get_tensor_by_name('num_detections:0')

# Get input/output tensors for Faster RCNN model
frcnn_image_tensor = frcnn_graph.get_tensor_by_name('image_tensor:0')
frcnn_boxes = frcnn_graph.get_tensor_by_name('detection_boxes:0')
frcnn_scores = frcnn_graph.get_tensor_by_name('detection_scores:0')
frcnn_classes = frcnn_graph.get_tensor_by_name('detection_classes:0')
frcnn_num_detections = frcnn_graph.get_tensor_by_name('num_detections:0')

# Load and combine label maps
# COCO uses IDs 1-90, so we offset custom classes to start at 91
coco_categories = label_map_util.create_category_index_from_labelmap(COCO_LABEL_MAP, use_display_name=True)
custom_categories = label_map_util.create_category_index_from_labelmap(CUSTOM_LABEL_MAP, use_display_name=True)

combined_categories = {}
# Add COCO classes first
combined_categories.update(coco_categories)
# Add custom classes with offset IDs
offset = 90
for idx, cat in custom_categories.items():
    new_idx = idx + offset
    combined_categories[new_idx] = {'id': new_idx, 'name': cat['name']}

4. Run Inference and Combine Results

# Load and preprocess input image
image = cv2.imread(INPUT_IMAGE_PATH)
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# Run inference with SSD (detects COCO classes)
ssd_det_boxes, ssd_det_scores, ssd_det_classes = run_inference(
    image_rgb, ssd_sess, ssd_image_tensor, ssd_boxes, ssd_scores, ssd_classes, ssd_num_detections
)

# Run inference with Faster RCNN (detects custom classes, IDs offset by 90)
frcnn_det_boxes, frcnn_det_scores, frcnn_det_classes = run_inference(
    image_rgb, frcnn_sess, frcnn_image_tensor, frcnn_boxes, frcnn_scores, frcnn_classes, frcnn_num_detections,
    class_id_offset=offset
)

# Combine all valid detections into single arrays
combined_boxes = np.concatenate([ssd_det_boxes, frcnn_det_boxes], axis=0)
combined_scores = np.concatenate([ssd_det_scores, frcnn_det_scores], axis=0)
combined_classes = np.concatenate([ssd_det_classes, frcnn_det_classes], axis=0)

5. Visualize and Save Results

# Draw combined detections on the image
vis_util.visualize_boxes_and_labels_on_image_array(
    image_rgb,
    combined_boxes,
    combined_classes,
    combined_scores,
    combined_categories,
    use_normalized_coordinates=True,
    line_thickness=4,
    min_score_thresh=0.5
)

# Convert back to BGR for OpenCV compatibility
image_bgr = cv2.cvtColor(image_rgb, cv2.COLOR_RGB2BGR)

# Display the result
cv2.imshow('Combined Object Detection', image_bgr)
cv2.waitKey(0)
cv2.destroyAllWindows()

# Save the output image
cv2.imwrite(OUTPUT_IMAGE_PATH, image_bgr)

# Clean up sessions to free resources
ssd_sess.close()
frcnn_sess.close()

Key Notes

  • Class ID Offset: The most important step is offsetting your custom model's class IDs by 90. This ensures no overlap between COCO's 1-90 IDs and your custom class IDs, preventing labeling confusion.
  • Threshold Adjustment: The 0.5 confidence threshold can be tuned up (for stricter detections) or down (for more detections) based on your needs.
  • TF Version: This code uses TensorFlow 1.x compatibility mode because the models you referenced are frozen graphs from older TF versions. If you're using TF 2.x, consider converting these models to SavedModel format for better performance.
  • Performance: Running two models sequentially will take longer than a single model, but it's the simplest way to combine their outputs without retraining a new multi-class model.

内容的提问来源于stack exchange,提问作者Prasad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:00:29