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

基于C++与OpenCV生成轮廓直方图的技术求助(多目标跟踪与遮挡识别)

Hey there! Let's work through your contour histogram problem—since you've already nailed contour detection, we're just a few steps away from building those histograms for multi-object tracking and occlusion recovery. Here's a straightforward, actionable approach tailored to your use case:

1. Extract the ROI for Each Contour

First, you need to grab the actual region of the object from your original color frame (not the subtracted grayscale one—color features are way more useful for distinguishing objects). For irregular shapes, you can use either a bounding rectangle or a precise mask based on the contour.

Option 1: Bounding Rectangle ROI (Faster)

// Assume you have your contours, hierarchy, and original color frame "frame"
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(frameSubtracao_gray.clone(), contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

// Loop through each detected contour
for (size_t i = 0; i < contours.size(); i++) {
    // Get the bounding rectangle of the contour
    cv::Rect roiRect = cv::boundingRect(contours[i]);
    // Extract the ROI from the original color frame
    cv::Mat objectRoi = frame(roiRect);

    // Convert ROI to HSV space (more stable for color histograms than BGR)
    cv::Mat hsvRoi;
    cv::cvtColor(objectRoi, hsvRoi, cv::COLOR_BGR2HSV);
}

Option 2: Precise Masked ROI (For Irregular Shapes)

If you want to ignore pixels outside the exact contour (e.g., for highly irregular objects), use a mask:

cv::Mat mask = cv::Mat::zeros(frame.size(), CV_8UC1);
// Draw and fill the contour on the mask
cv::drawContours(mask, contours, i, cv::Scalar(255), cv::FILLED);

// Extract the ROI using the mask
cv::Mat objectRoi;
frame.copyTo(objectRoi, mask);
cv::Mat hsvRoi;
cv::cvtColor(objectRoi, hsvRoi, cv::COLOR_BGR2HSV);
2. Calculate the Histogram for the ROI

We'll use the H (hue) and S (saturation) channels of HSV—they're less sensitive to lighting changes than brightness (V). Here's how to compute and normalize the histogram:

// Define histogram parameters
int hueBins = 50;
int satBins = 60;
int histSize[] = {hueBins, satBins};
// HSV ranges: Hue 0-179, Saturation 0-255
float hueRanges[] = {0, 180};
float satRanges[] = {0, 256};
const float* ranges[] = {hueRanges, satRanges};
// Channels to use: H (0) and S (1)
int channels[] = {0, 1};

// Compute the histogram
cv::Mat objectHist;
cv::calcHist(&hsvRoi, 1, channels, cv::Mat(), objectHist, 2, histSize, ranges, true, false);

// Normalize the histogram (makes comparison easier later)
cv::normalize(objectHist, objectHist, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
3. Use Histograms for Tracking & Occlusion Recovery

To match new detected objects with your tracked targets, compare their histograms using a similarity metric. The Bhattacharyya distance works great here—lower values mean more similar histograms.

// Assume you have a stored histogram for a tracked target "targetHist"
double similarity = cv::compareHist(objectHist, targetHist, cv::HISTCMP_BHATTACHARYYA);

// Adjust the threshold based on your testing (e.g., <0.3 = match)
if (similarity < 0.3) {
    // This new object matches your tracked target!
}
Key Tips for Success
  • Never use the subtracted grayscale frame for histograms—it only has foreground/background info, no color details to distinguish objects. Always use the original color frame's ROI.
  • For multi-target tracking, store each target's histogram alongside an ID and last known position (e.g., in a struct like struct TrackedTarget { int id; cv::Mat hist; cv::Rect lastPos; };).
  • If occlusion happens, keep the target's histogram stored and re-match it when the object reappears.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:15:26