00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <swri_image_util/draw_util.h>
00031
00032 #include <cstdlib>
00033 #include <algorithm>
00034
00035 #include <opencv2/imgproc/imgproc.hpp>
00036 #include <opencv2/calib3d/calib3d.hpp>
00037
00038 #include <ros/ros.h>
00039
00040 #include <swri_opencv_util/show.h>
00041
00042 namespace swri_image_util
00043 {
00044 void RandomColor(int32_t seed, double& r, double& g, double& b)
00045 {
00046 std::srand(seed);
00047
00048 r = static_cast<double>(std::rand()) / RAND_MAX;
00049 g = static_cast<double>(std::rand()) / RAND_MAX;
00050 b = static_cast<double>(std::rand()) / RAND_MAX;
00051 }
00052
00053 void JetColorMap(
00054 unsigned char &r,
00055 unsigned char &g,
00056 unsigned char &b,
00057 float value,
00058 float min,
00059 float max)
00060 {
00061 float max4 = (max - min) / 4.0;
00062 value -= min;
00063
00064 if (value == HUGE_VAL)
00065 {
00066 r = g = b = 255;
00067 }
00068 else if (value < 0)
00069 {
00070 r = g = b = 0;
00071 }
00072 else if (value < max4)
00073 {
00074 unsigned char c1 = 144;
00075
00076 r = 0;
00077 g = 0;
00078 b = c1 + (unsigned char) ((255 - c1) * value / max4);
00079 }
00080 else if (value < 2 * max4)
00081 {
00082 r = 0;
00083 g = (unsigned char) (255 * (value - max4) / max4);
00084 b = 255;
00085 }
00086 else if (value < 3 * max4)
00087 {
00088 r = (unsigned char) (255 * (value - 2 * max4) / max4);
00089 g = 255;
00090 b = 255 - r;
00091 }
00092 else if (value < max)
00093 {
00094 r = 255;
00095 g = (unsigned char) (255 - 255 * (value - 3 * max4) / max4);
00096 b = 0;
00097 }
00098 else
00099 {
00100 r = 255;
00101 g = 0;
00102 b = 0;
00103 }
00104 }
00105
00106 void DrawOverlap(
00107 const std::string& title,
00108 const cv::Mat& image1,
00109 const cv::Mat& image2,
00110 const cv::Mat& transform)
00111 {
00112 if (image1.rows == image2.rows && image1.cols == image2.cols)
00113 {
00114 cv::Mat image2_warped;
00115 cv::warpAffine(
00116 image2,
00117 image2_warped,
00118 transform,
00119 cv::Size(image2.cols, image2.rows));
00120
00121 cv::Mat sub = image1 - image2_warped;
00122
00123 swri_opencv_util::ShowScaled(title, sub);
00124 }
00125 }
00126
00127 void DrawMatches(
00128 cv::Mat& image_out,
00129 const cv::Mat image1,
00130 const cv::Mat image2,
00131 const cv::Mat points1,
00132 const cv::Mat points2,
00133 const cv::Scalar& color,
00134 bool draw_image_borders)
00135 {
00136 cv::Size size(image1.cols + image2.cols, std::max(image1.rows, image2.rows));
00137 image_out.create(size, CV_MAKETYPE(image1.depth(), 3));
00138 cv::Mat draw_image1 = image_out(cv::Rect(0, 0, image1.cols, image1.rows));
00139 cv::Mat draw_image2 = image_out(cv::Rect(image1.cols, 0, image2.cols, image2.rows));
00140
00141 if (image1.type() == CV_8U)
00142 {
00143 cvtColor(image1, draw_image1, CV_GRAY2BGR);
00144 }
00145 else
00146 {
00147 image1.copyTo(draw_image1);
00148 }
00149
00150 if (image2.type() == CV_8U)
00151 {
00152 cvtColor(image2, draw_image2, CV_GRAY2BGR);
00153 }
00154 else
00155 {
00156 image2.copyTo(draw_image2);
00157 }
00158
00159 if (draw_image_borders)
00160 {
00161 cv::rectangle(draw_image1,
00162 cv::Point(0, 0),
00163 cv::Point(image1.cols, image1.rows),
00164 cv::Scalar(0, 0, 0),
00165 2);
00166
00167 cv::rectangle(draw_image2,
00168 cv::Point(0, 0),
00169 cv::Point(image2.cols, image2.rows),
00170 cv::Scalar(0, 0, 0),
00171 2);
00172 }
00173
00174 cv::RNG rng = cv::theRNG();
00175 bool rand_color = color == cv::Scalar::all(-1);
00176
00177 for (int i = 0; i < points1.rows; i++)
00178 {
00179 cv::Scalar match_color = rand_color ? cv::Scalar(rng(256), rng(256), rng(256)) : color;
00180 cv::Point2f center1(
00181 cvRound(points1.at<cv::Vec2f>(0, i)[0] * 16.0),
00182 cvRound(points1.at<cv::Vec2f>(0, i)[1] * 16.0));
00183 cv::Point2f center2(
00184 cvRound(points2.at<cv::Vec2f>(0, i)[0] * 16.0),
00185 cvRound(points2.at<cv::Vec2f>(0, i)[1] * 16.0));
00186 cv::Point2f dcenter2(
00187 std::min(center2.x + draw_image1.cols * 16.0, (image_out.cols - 1) * 16.0),
00188 center2.y);
00189 circle(draw_image1, center1, 48, match_color, 1, CV_AA, 4);
00190 circle(draw_image2, center2, 48, match_color, 1, CV_AA, 4);
00191 line(image_out, center1, dcenter2, match_color, 1, CV_AA, 4);
00192 }
00193 }
00194
00195 void DrawMatches(
00196 const std::string& title,
00197 const cv::Mat image1,
00198 const cv::Mat image2,
00199 const cv::Mat points1,
00200 const cv::Mat points2,
00201 const cv::Scalar& color,
00202 bool draw_image_borders)
00203 {
00204 cv::Mat image_out;
00205 DrawMatches(image_out,
00206 image1,
00207 image2,
00208 points1,
00209 points2,
00210 color,
00211 draw_image_borders);
00212
00213 swri_opencv_util::ShowScaled(title, image_out);
00214 }
00215
00216 void DrawMatches(
00217 const std::string& title,
00218 const cv::Mat image,
00219 const cv::Mat points1,
00220 const cv::Mat points2,
00221 const cv::Scalar& color1,
00222 const cv::Scalar& color2,
00223 bool draw_image_borders)
00224 {
00225 cv::Mat draw_image;
00226 if (image.type() == CV_8U)
00227 {
00228 cvtColor(image, draw_image, CV_GRAY2BGR);
00229 }
00230 else
00231 {
00232 draw_image = image.clone();
00233 }
00234
00235 for (int i = 0; i < points1.rows; i++)
00236 {
00237 cv::Point2f center1(
00238 cvRound(points1.at<cv::Vec2f>(0, i)[0] * 16.0),
00239 cvRound(points1.at<cv::Vec2f>(0, i)[1] * 16.0));
00240 cv::Point2f center2(cvRound(
00241 points2.at<cv::Vec2f>(0, i)[0] * 16.0),
00242 cvRound(points2.at<cv::Vec2f>(0, i)[1] * 16.0));
00243 circle(draw_image, center1, 48, color1, 1, CV_AA, 4);
00244 line(draw_image, center1, center2, color2, 1, CV_AA, 4);
00245 }
00246
00247 swri_opencv_util::ShowScaled(title, draw_image);
00248 }
00249 }