/*! @brief visualize the candidate part locations overlaid on an image * * @param im the image * @param candidates a vector of type Candidate, representing potential * part locations * @param N the number of candidates to render. If the candidates have been sorted, * this is equivalent to displaying only the 'N best' candidates * @param display_confidence display the detection confidence above each bounding box * for each part */ void Visualize::candidates(const Mat& im, const vectorCandidate& candidates, unsigned int N, Mat& canvas, bool display_confidence) const { // create a new canvas that we can modify cvtColor(im, canvas, CV_RGB2BGR); if (candidates.size() == 0) return; // generate a set of colors to display. Do this in HSV then convert it const unsigned int ncolors = candidates[0].parts().size(); vector<Scalar> colors; for (unsigned int n = 0; n < ncolors; ++n) { Mat color(Size(1,1), CV_32FC3); // Hue is in degrees, not radians (because consistency is over-rated) color.at<float>(0) = (360) / ncolors * n; color.at<float>(1) = 1.0; color.at<float>(2) = 0.7; cvtColor(color, color, CV_HSV2BGR); color = color * 255; colors.push_back(Scalar(color.at<float>(0), color.at<float>(1), color.at<float>(2))); } // draw each candidate to the canvas const int LINE_THICKNESS = 4; Scalar black(0,0,0); N = (candidates.size() < N) ? candidates.size() : N; for (unsigned int n = 0; n < N; ++n) { Candidate candidate = candidates[n]; for (unsigned int p = 0; p < candidate.parts().size(); ++p) { Rect box = candidate.parts()[p]; string confidence = boost::lexical_cast<string>(candidate.confidence()[p]); rectangle(canvas, box, colors[p], LINE_THICKNESS); if (display_confidence && p == 0) putText(canvas, confidence, Point(box.x, box.y-5), FONT_HERSHEY_SIMPLEX, 0.5f, black, 2); } //rectangle(canvas, candidate.boundingBox(), Scalar(255, 0, 0), LINE_THICKNESS); } }
void PartsBasedDetectorNode::messagePartsImage(const vectorCandidate& candidates, const std::vector< std::vector<cv::Point3d> >& parts_centers, Mat& rgb, const ImageConstPtr& msg_in) { // draw each part of a candidate Mat canvas; cv_bridge::CvImage container; const size_t nparts = candidates.size(); double part_x, part_y; cvtColor(rgb, canvas, COLOR_RGB2BGR); const size_t ncolors = candidates[0].parts().size(); vector<Scalar> colors; for (size_t n = 0; n < ncolors; ++n) { Mat color(Size(1,1), CV_32FC3); // Hue is in degrees, not radians (because consistency is over-rated) color.at<float>(0) = (360) / ncolors * n; color.at<float>(1) = 1.0; color.at<float>(2) = 0.7; cvtColor(color, color, COLOR_HSV2BGR); color = color * 255; colors.push_back(Scalar(color.at<float>(0), color.at<float>(1), color.at<float>(2))); } const int LINE_THICKNESS = 5; Scalar black(0,0,0); for (size_t n = 0; n < nparts; ++n) { Candidate candidate = candidates[n]; for (size_t p = 0; p < candidate.parts().size(); ++p) { part_x = parts_centers[n][p].x; part_y = parts_centers[n][p].y; rectangle(canvas, Point(part_x, part_y), Point(part_x, part_y), colors[p], LINE_THICKNESS); stringstream number_; number_ << (p+1); string part_number = number_.str(); putText(canvas, part_number, Point(part_x, part_y), FONT_HERSHEY_SIMPLEX, 0.5f, colors[p], 2); } } container.image = canvas; container.encoding = enc::RGB8; ImagePtr msg_out = container.toImageMsg(); msg_out->header.frame_id = msg_in->header.frame_id; msg_out->header.stamp = msg_in->header.stamp; image_pub_part_.publish(msg_out); }