void Yolov5PostProcess::nms(vector<vector<float>>& boxes, vector<int>& idxes, float threshold) { map<int, int> idx_map; for (int i = 0; i < boxes.size() - 1; ++i) { if (idx_map.find(i) != idx_map.end()) { continue; } for (int j = i + 1; j < boxes.size(); ++j) { if (idx_map.find(j) != idx_map.end()) { continue; } vector<float> Bbox1, Bbox2; Bbox1.push_back(boxes[i][0]); Bbox1.push_back(boxes[i][1]); Bbox1.push_back(boxes[i][2]); Bbox1.push_back(boxes[i][3]); Bbox2.push_back(boxes[j][0]); Bbox2.push_back(boxes[j][1]); Bbox2.push_back(boxes[j][2]); Bbox2.push_back(boxes[j][3]); float iou = box_iou(Bbox1, Bbox2); if (iou >= threshold) { idx_map[j] = 1; } } } for (int i = 0; i < boxes.size(); ++i) { if (idx_map.find(i) == idx_map.end()) { idxes.push_back(i); } } }详细解读一下这段代码
时间: 2024-04-28 21:23:50 浏览: 181
这段代码实现的是非极大值抑制(Non-Maximum Suppression,NMS)的功能,用于在目标检测中去除重复的边界框。
具体来说,这段代码输入参数 `boxes` 是一个二维数组,每一行代表一个边界框,其中每行的四个元素分别是左上角 x 坐标、左上角 y 坐标、右下角 x 坐标和右下角 y 坐标。`threshold` 是一个阈值,用于控制重叠度的大小,当两个边界框的重叠度大于等于该阈值时,就认为它们是重复的边界框之一,需要将其中一个去掉。
该代码首先创建了一个 `idx_map` 的 `map` 对象,用于记录需要去掉的边界框的索引。然后使用两重循环遍历所有边界框,对于每对边界框,计算它们的重叠度(即交并比,通过 `box_iou` 函数实现),如果大于等于阈值 `threshold`,则将其中一个边界框的索引加入到 `idx_map` 中。最后遍历所有边界框的索引,将不在 `idx_map` 中的索引加入到输出参数 `idxes` 中,即完成了非极大值抑制的过程。
相关问题
在vs2015 c++ .h中加入这段代码会报重定义 namespace cv_dnn { namespace { template <typename T> static inline bool SortScorePairDescend(const std::pair<float, T>& pair1, const std::pair<float, T>& pair2) { return pair1.first > pair2.first; } } // namespace inline void GetMaxScoreIndex(const std::vector<float>& scores, const float threshold, const int top_k, std::vector<std::pair<float, int> >& score_index_vec) { for (size_t i = 0; i < scores.size(); ++i) { if (scores[i] > threshold) { score_index_vec.push_back(std::make_pair(scores[i], i)); } } std::stable_sort(score_index_vec.begin(), score_index_vec.end(), SortScorePairDescend<int>); if (top_k > 0 && top_k < (int)score_index_vec.size()) { score_index_vec.resize(top_k); } } template <typename BoxType> inline void NMSFast_(const std::vector<BoxType>& bboxes, const std::vector<float>& scores, const float score_threshold, const float nms_threshold, const float eta, const int top_k, std::vector<int>& indices, float(*computeOverlap)(const BoxType&, const BoxType&)) { CV_Assert(bboxes.size() == scores.size()); std::vector<std::pair<float, int> > score_index_vec; GetMaxScoreIndex(scores, score_threshold, top_k, score_index_vec); // Do nms. float adaptive_threshold = nms_threshold; indices.clear(); for (size_t i = 0; i < score_index_vec.size(); ++i) { const int idx = score_index_vec[i].second; bool keep = true; for (int k = 0; k < (int)indices.size() && keep; ++k) { const int kept_idx = indices[k]; float overlap = computeOverlap(bboxes[idx], bboxes[kept_idx]); keep = overlap <= adaptive_threshold; } if (keep) indices.push_back(idx); if (keep && eta < 1 && adaptive_threshold > 0.5) { adaptive_threshold *= eta; } } } // copied from opencv 3.4, not exist in 3.0 template<typename Tp> static inline double jaccardDistance_(const Rect_<Tp>& a, const Rect<_Tp>& b) { Tp Aa = a.area(); Tp Ab = b.area(); if ((Aa + Ab) <= std::numeric_limits<Tp>::epsilon()) { // jaccard_index = 1 -> distance = 0 return 0.0; } double Aab = (a & b).area(); // distance = 1 - jaccard_index return 1.0 - Aab / (Aa + Ab - Aab); } template <typename T> static inline float rectOverlap(const T& a, const T& b) { return 1.f - static_cast<float>(jaccardDistance(a, b)); } void NMSBoxes(const std::vector<Rect>& bboxes, const std::vector<float>& scores, const float score_threshold, const float nms_threshold, std::vector<int>& indices, const float eta = 1, const int top_k = 0) { NMSFast(bboxes, scores, score_threshold, nms_threshold, eta, top_k, indices, rectOverlap); } }
在加入这段代码时,如果在同一个命名空间内有相同的函数或变量,则会报重定义的错误。如果你确定已经检查过代码,在其他地方没有定义相同的函数或变量,可以尝试将代码放在一个新的命名空间中。例如:
```cpp
namespace my_cv_dnn {
// 这里放你的代码
}
```
然后在使用时使用新的命名空间即可。
std::vector<int> nms_result; cv::dnn::NMSBoxes(boxes, confidences, CONF_THRESHOLD, NMS_THRESHOLD, nms_result); std::vector<cv::Mat> temp_mask_proposals; std::vector<OutputSeg> output; Rect holeImgRect(0, 0, src.cols, src.rows); for (int i = 0; i < nms_result.size(); ++i) { int idx = nms_result[i]; OutputSeg result; result.id = classIds[idx]; result.confidence = confidences[idx]; result.box = boxes[idx]& holeImgRect; output.push_back(result); temp_mask_proposals.push_back(picked_proposals[idx]); }什么意思
这段代码是一个目标检测算法的一部分,它使用非极大值抑制(NMS)来筛选出具有高置信度的目标框。首先,它调用了cv::dnn::NMSBoxes函数,该函数会根据指定的阈值将置信度低于阈值的目标框过滤掉,并将保留的目标框的索引存储在nms_result向量中。
然后,通过遍历nms_result向量,获取每个保留目标框的索引。接下来,创建一个OutputSeg结构体变量result,将目标类别id、置信度和经过修剪的目标框赋值给result。然后,将result添加到output向量中,并将对应的临时掩码提案添加到temp_mask_proposals向量中。
最后,将经过筛选后的结果存储在output向量中,并将对应的临时掩码提案存储在temp_mask_proposals向量中。整个过程旨在选择具有高置信度的目标框,并将与之相关的信息存储到output和temp_mask_proposals中以供后续使用。
阅读全文