117 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			117 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2019 The MediaPipe Authors.
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //      http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| #include "mediapipe/util/tracking/image_util.h"
 | |
| 
 | |
| #include <algorithm>
 | |
| #include <vector>
 | |
| 
 | |
| #include "mediapipe/framework/port/logging.h"
 | |
| #include "mediapipe/util/tracking/motion_models.h"
 | |
| #include "mediapipe/util/tracking/region_flow.h"
 | |
| 
 | |
| namespace mediapipe {
 | |
| 
 | |
| // Returns median of the L1 color distance between img_1 and img_2
 | |
| float FrameDifferenceMedian(const cv::Mat& img_1, const cv::Mat& img_2) {
 | |
|   CHECK(img_1.size() == img_2.size());
 | |
|   CHECK_EQ(img_1.channels(), img_2.channels());
 | |
| 
 | |
|   std::vector<float> color_diffs;
 | |
|   color_diffs.reserve(img_1.cols * img_1.rows);
 | |
|   const int channels = img_1.channels();
 | |
|   for (int j = 0; j < img_1.rows; ++j) {
 | |
|     const uint8* src_1 = img_1.ptr<uint8>(j);
 | |
|     const uint8* src_2 = img_2.ptr<uint8>(j);
 | |
|     const int end_i = channels * img_1.cols;
 | |
|     const float inverse = 1.0f / channels;
 | |
|     for (int i = 0; i < end_i;) {
 | |
|       float color_diff = 0.0f;
 | |
|       for (int k = 0; k < channels; ++k, ++i) {
 | |
|         color_diff +=
 | |
|             std::abs(static_cast<int>(src_1[i]) - static_cast<int>(src_2[i]));
 | |
|       }
 | |
|       color_diffs.push_back(color_diff * inverse);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   auto median = color_diffs.begin() + color_diffs.size() / 2;
 | |
|   std::nth_element(color_diffs.begin(), median, color_diffs.end());
 | |
|   return *median;
 | |
| }
 | |
| 
 | |
| void JetColoring(int steps, std::vector<Vector3_f>* color_map) {
 | |
|   CHECK(color_map != nullptr);
 | |
|   color_map->resize(steps);
 | |
|   for (int i = 0; i < steps; ++i) {
 | |
|     const float frac = 2.0f * (i * (1.0f / steps) - 0.5f);
 | |
|     if (frac < -0.8f) {
 | |
|       (*color_map)[i] = Vector3_f(0, 0, 0.6f + (frac + 1.0) * 2.0f) * 255.0f;
 | |
|     } else if (frac >= -0.8f && frac < -0.25f) {
 | |
|       (*color_map)[i] = Vector3_f(0, (frac + 0.8f) * 1.82f, 1.0f) * 255.0f;
 | |
|     } else if (frac >= -0.25f && frac < 0.25f) {
 | |
|       (*color_map)[i] =
 | |
|           Vector3_f((frac + 0.25f) * 2.0f, 1.0f, 1.0 + (frac + 0.25f) * -2.0f) *
 | |
|           255.0f;
 | |
|     } else if (frac >= 0.25f && frac < 0.8f) {
 | |
|       (*color_map)[i] =
 | |
|           Vector3_f(1.0f, 1.0f + (frac - 0.25f) * -1.81f, 0.0f) * 255.0f;
 | |
|     } else if (frac >= 0.8f) {
 | |
|       (*color_map)[i] =
 | |
|           Vector3_f(1.0f + (frac - 0.8f) * -2.0f, 0.0f, 0.0f) * 255.0f;
 | |
|     } else {
 | |
|       LOG(ERROR) << "Out of bound value. Should not occur.";
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| void RenderSaliency(const SalientPointFrame& salient_points,
 | |
|                     const cv::Scalar& line_color, int line_thickness,
 | |
|                     bool render_bounding_box, cv::Mat* image) {
 | |
|   // Visualize salient points.
 | |
|   for (const auto& point : salient_points.point()) {
 | |
|     if (point.weight() > 0) {
 | |
|       SalientPoint copy = point;
 | |
|       ScaleSalientPoint(image->cols, image->rows, ©);
 | |
|       Vector2_f pt(copy.norm_point_x(), copy.norm_point_y());
 | |
| 
 | |
|       cv::ellipse(*image, cv::Point(pt.x(), pt.y()),
 | |
|                   cv::Size(copy.norm_major(), copy.norm_minor()),
 | |
|                   copy.angle() / M_PI * 180.0,
 | |
|                   0,    // start angle
 | |
|                   360,  // end angle
 | |
|                   line_color, line_thickness);
 | |
| 
 | |
|       if (render_bounding_box) {
 | |
|         std::vector<Vector2_f> ellipse_bounding_box;
 | |
|         BoundingBoxFromEllipse(pt, copy.norm_major(), copy.norm_minor(),
 | |
|                                copy.angle(), &ellipse_bounding_box);
 | |
| 
 | |
|         std::vector<cv::Point> corners;
 | |
|         corners.reserve(4);
 | |
|         for (const Vector2_f& corner : ellipse_bounding_box) {
 | |
|           corners.emplace_back(cv::Point(corner.x(), corner.y()));
 | |
|         }
 | |
| 
 | |
|         for (int k = 0; k < 4; ++k) {
 | |
|           cv::line(*image, corners[k], corners[(k + 1) % 4], line_color,
 | |
|                    line_thickness, cv::LINE_AA);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| }  // namespace mediapipe
 |