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 image_out.setTo(cv::Vec3b(0, 0, 0));
00139 cv::Mat draw_image1 = image_out(cv::Rect(0, 0, image1.cols, image1.rows));
00140 cv::Mat draw_image2 = image_out(cv::Rect(image1.cols, 0, image2.cols, image2.rows));
00141
00142 if (image1.type() == CV_8U)
00143 {
00144 cvtColor(image1, draw_image1, CV_GRAY2BGR);
00145 }
00146 else
00147 {
00148 image1.copyTo(draw_image1);
00149 }
00150
00151 if (image2.type() == CV_8U)
00152 {
00153 cvtColor(image2, draw_image2, CV_GRAY2BGR);
00154 }
00155 else
00156 {
00157 image2.copyTo(draw_image2);
00158 }
00159
00160 if (draw_image_borders)
00161 {
00162 cv::rectangle(draw_image1,
00163 cv::Point(0, 0),
00164 cv::Point(image1.cols, image1.rows),
00165 cv::Scalar(0, 0, 0),
00166 2);
00167
00168 cv::rectangle(draw_image2,
00169 cv::Point(0, 0),
00170 cv::Point(image2.cols, image2.rows),
00171 cv::Scalar(0, 0, 0),
00172 2);
00173 }
00174
00175 cv::RNG rng = cv::theRNG();
00176 bool rand_color = color == cv::Scalar::all(-1);
00177
00178 for (int i = 0; i < points1.rows; i++)
00179 {
00180 cv::Scalar match_color = rand_color ? cv::Scalar(rng(256), rng(256), rng(256)) : color;
00181 cv::Point2f center1(
00182 cvRound(points1.at<cv::Vec2f>(0, i)[0] * 16.0),
00183 cvRound(points1.at<cv::Vec2f>(0, i)[1] * 16.0));
00184 cv::Point2f center2(
00185 cvRound(points2.at<cv::Vec2f>(0, i)[0] * 16.0),
00186 cvRound(points2.at<cv::Vec2f>(0, i)[1] * 16.0));
00187 cv::Point2f dcenter2(
00188 std::min(center2.x + draw_image1.cols * 16.0, (image_out.cols - 1) * 16.0),
00189 center2.y);
00190 circle(draw_image1, center1, 48, match_color, 1, CV_AA, 4);
00191 circle(draw_image2, center2, 48, match_color, 1, CV_AA, 4);
00192 line(image_out, center1, dcenter2, match_color, 1, CV_AA, 4);
00193 }
00194 }
00195
00196 void DrawMatches(
00197 const std::string& title,
00198 const cv::Mat image1,
00199 const cv::Mat image2,
00200 const cv::Mat points1,
00201 const cv::Mat points2,
00202 const cv::Scalar& color,
00203 bool draw_image_borders)
00204 {
00205 cv::Mat image_out;
00206 DrawMatches(image_out,
00207 image1,
00208 image2,
00209 points1,
00210 points2,
00211 color,
00212 draw_image_borders);
00213
00214 swri_opencv_util::ShowScaled(title, image_out);
00215 }
00216
00217 void DrawMatches(
00218 const std::string& title,
00219 const cv::Mat image,
00220 const cv::Mat points1,
00221 const cv::Mat points2,
00222 const cv::Scalar& color1,
00223 const cv::Scalar& color2,
00224 bool draw_image_borders)
00225 {
00226 cv::Mat draw_image;
00227 if (image.type() == CV_8U)
00228 {
00229 cvtColor(image, draw_image, CV_GRAY2BGR);
00230 }
00231 else
00232 {
00233 draw_image = image.clone();
00234 }
00235
00236 for (int i = 0; i < points1.rows; i++)
00237 {
00238 cv::Point2f center1(
00239 cvRound(points1.at<cv::Vec2f>(0, i)[0] * 16.0),
00240 cvRound(points1.at<cv::Vec2f>(0, i)[1] * 16.0));
00241 cv::Point2f center2(cvRound(
00242 points2.at<cv::Vec2f>(0, i)[0] * 16.0),
00243 cvRound(points2.at<cv::Vec2f>(0, i)[1] * 16.0));
00244 circle(draw_image, center1, 48, color1, 1, CV_AA, 4);
00245 line(draw_image, center1, center2, color2, 1, CV_AA, 4);
00246 }
00247
00248 swri_opencv_util::ShowScaled(title, draw_image);
00249 }
00250 }