1/*M/////////////////////////////////////////////////////////////////////////////////////// 2// 3// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4// 5// By downloading, copying, installing or using the software you agree to this license. 6// If you do not agree to this license, do not download, install, 7// copy or use the software. 8// 9// 10// Intel License Agreement 11// For Open Source Computer Vision Library 12// 13// Copyright (C) 2000, Intel Corporation, all rights reserved. 14// Third party copyrights are property of their respective owners. 15// 16// Redistribution and use in source and binary forms, with or without modification, 17// are permitted provided that the following conditions are met: 18// 19// * Redistribution's of source code must retain the above copyright notice, 20// this list of conditions and the following disclaimer. 21// 22// * Redistribution's in binary form must reproduce the above copyright notice, 23// this list of conditions and the following disclaimer in the documentation 24// and/or other materials provided with the distribution. 25// 26// * The name of Intel Corporation may not be used to endorse or promote products 27// derived from this software without specific prior written permission. 28// 29// This software is provided by the copyright holders and contributors "as is" and 30// any express or implied warranties, including, but not limited to, the implied 31// warranties of merchantability and fitness for a particular purpose are disclaimed. 32// In no event shall the Intel Corporation or contributors be liable for any direct, 33// indirect, incidental, special, exemplary, or consequential damages 34// (including, but not limited to, procurement of substitute goods or services; 35// loss of use, data, or profits; or business interruption) however caused 36// and on any theory of liability, whether in contract, strict liability, 37// or tort (including negligence or otherwise) arising in any way out of 38// the use of this software, even if advised of the possibility of such damage. 39// 40//M*/ 41 42#include "precomp.hpp" 43 44const int draw_shift_bits = 4; 45const int draw_multiplier = 1 << draw_shift_bits; 46 47namespace cv 48{ 49 50/* 51 * Functions to draw keypoints and matches. 52 */ 53static inline void _drawKeypoint( InputOutputArray img, const KeyPoint& p, const Scalar& color, int flags ) 54{ 55 CV_Assert( !img.empty() ); 56 Point center( cvRound(p.pt.x * draw_multiplier), cvRound(p.pt.y * draw_multiplier) ); 57 58 if( flags & DrawMatchesFlags::DRAW_RICH_KEYPOINTS ) 59 { 60 int radius = cvRound(p.size/2 * draw_multiplier); // KeyPoint::size is a diameter 61 62 // draw the circles around keypoints with the keypoints size 63 circle( img, center, radius, color, 1, LINE_AA, draw_shift_bits ); 64 65 // draw orientation of the keypoint, if it is applicable 66 if( p.angle != -1 ) 67 { 68 float srcAngleRad = p.angle*(float)CV_PI/180.f; 69 Point orient( cvRound(cos(srcAngleRad)*radius ), 70 cvRound(sin(srcAngleRad)*radius ) 71 ); 72 line( img, center, center+orient, color, 1, LINE_AA, draw_shift_bits ); 73 } 74#if 0 75 else 76 { 77 // draw center with R=1 78 int radius = 1 * draw_multiplier; 79 circle( img, center, radius, color, 1, LINE_AA, draw_shift_bits ); 80 } 81#endif 82 } 83 else 84 { 85 // draw center with R=3 86 int radius = 3 * draw_multiplier; 87 circle( img, center, radius, color, 1, LINE_AA, draw_shift_bits ); 88 } 89} 90 91void drawKeypoints( InputArray image, const std::vector<KeyPoint>& keypoints, InputOutputArray outImage, 92 const Scalar& _color, int flags ) 93{ 94 if( !(flags & DrawMatchesFlags::DRAW_OVER_OUTIMG) ) 95 { 96 if( image.type() == CV_8UC3 ) 97 { 98 image.copyTo( outImage ); 99 } 100 else if( image.type() == CV_8UC1 ) 101 { 102 cvtColor( image, outImage, COLOR_GRAY2BGR ); 103 } 104 else 105 { 106 CV_Error( Error::StsBadArg, "Incorrect type of input image.\n" ); 107 } 108 } 109 110 RNG& rng=theRNG(); 111 bool isRandColor = _color == Scalar::all(-1); 112 113 CV_Assert( !outImage.empty() ); 114 std::vector<KeyPoint>::const_iterator it = keypoints.begin(), 115 end = keypoints.end(); 116 for( ; it != end; ++it ) 117 { 118 Scalar color = isRandColor ? Scalar(rng(256), rng(256), rng(256)) : _color; 119 _drawKeypoint( outImage, *it, color, flags ); 120 } 121} 122 123static void _prepareImgAndDrawKeypoints( InputArray img1, const std::vector<KeyPoint>& keypoints1, 124 InputArray img2, const std::vector<KeyPoint>& keypoints2, 125 InputOutputArray _outImg, Mat& outImg1, Mat& outImg2, 126 const Scalar& singlePointColor, int flags ) 127{ 128 Mat outImg; 129 Size img1size = img1.size(), img2size = img2.size(); 130 Size size( img1size.width + img2size.width, MAX(img1size.height, img2size.height) ); 131 if( flags & DrawMatchesFlags::DRAW_OVER_OUTIMG ) 132 { 133 outImg = _outImg.getMat(); 134 if( size.width > outImg.cols || size.height > outImg.rows ) 135 CV_Error( Error::StsBadSize, "outImg has size less than need to draw img1 and img2 together" ); 136 outImg1 = outImg( Rect(0, 0, img1size.width, img1size.height) ); 137 outImg2 = outImg( Rect(img1size.width, 0, img2size.width, img2size.height) ); 138 } 139 else 140 { 141 _outImg.create( size, CV_MAKETYPE(img1.depth(), 3) ); 142 outImg = _outImg.getMat(); 143 outImg = Scalar::all(0); 144 outImg1 = outImg( Rect(0, 0, img1size.width, img1size.height) ); 145 outImg2 = outImg( Rect(img1size.width, 0, img2size.width, img2size.height) ); 146 147 if( img1.type() == CV_8U ) 148 cvtColor( img1, outImg1, COLOR_GRAY2BGR ); 149 else 150 img1.copyTo( outImg1 ); 151 152 if( img2.type() == CV_8U ) 153 cvtColor( img2, outImg2, COLOR_GRAY2BGR ); 154 else 155 img2.copyTo( outImg2 ); 156 } 157 158 // draw keypoints 159 if( !(flags & DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS) ) 160 { 161 Mat _outImg1 = outImg( Rect(0, 0, img1size.width, img1size.height) ); 162 drawKeypoints( _outImg1, keypoints1, _outImg1, singlePointColor, flags | DrawMatchesFlags::DRAW_OVER_OUTIMG ); 163 164 Mat _outImg2 = outImg( Rect(img1size.width, 0, img2size.width, img2size.height) ); 165 drawKeypoints( _outImg2, keypoints2, _outImg2, singlePointColor, flags | DrawMatchesFlags::DRAW_OVER_OUTIMG ); 166 } 167} 168 169static inline void _drawMatch( InputOutputArray outImg, InputOutputArray outImg1, InputOutputArray outImg2 , 170 const KeyPoint& kp1, const KeyPoint& kp2, const Scalar& matchColor, int flags ) 171{ 172 RNG& rng = theRNG(); 173 bool isRandMatchColor = matchColor == Scalar::all(-1); 174 Scalar color = isRandMatchColor ? Scalar( rng(256), rng(256), rng(256) ) : matchColor; 175 176 _drawKeypoint( outImg1, kp1, color, flags ); 177 _drawKeypoint( outImg2, kp2, color, flags ); 178 179 Point2f pt1 = kp1.pt, 180 pt2 = kp2.pt, 181 dpt2 = Point2f( std::min(pt2.x+outImg1.size().width, float(outImg.size().width-1)), pt2.y ); 182 183 line( outImg, 184 Point(cvRound(pt1.x*draw_multiplier), cvRound(pt1.y*draw_multiplier)), 185 Point(cvRound(dpt2.x*draw_multiplier), cvRound(dpt2.y*draw_multiplier)), 186 color, 1, LINE_AA, draw_shift_bits ); 187} 188 189void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1, 190 InputArray img2, const std::vector<KeyPoint>& keypoints2, 191 const std::vector<DMatch>& matches1to2, InputOutputArray outImg, 192 const Scalar& matchColor, const Scalar& singlePointColor, 193 const std::vector<char>& matchesMask, int flags ) 194{ 195 if( !matchesMask.empty() && matchesMask.size() != matches1to2.size() ) 196 CV_Error( Error::StsBadSize, "matchesMask must have the same size as matches1to2" ); 197 198 Mat outImg1, outImg2; 199 _prepareImgAndDrawKeypoints( img1, keypoints1, img2, keypoints2, 200 outImg, outImg1, outImg2, singlePointColor, flags ); 201 202 // draw matches 203 for( size_t m = 0; m < matches1to2.size(); m++ ) 204 { 205 if( matchesMask.empty() || matchesMask[m] ) 206 { 207 int i1 = matches1to2[m].queryIdx; 208 int i2 = matches1to2[m].trainIdx; 209 CV_Assert(i1 >= 0 && i1 < static_cast<int>(keypoints1.size())); 210 CV_Assert(i2 >= 0 && i2 < static_cast<int>(keypoints2.size())); 211 212 const KeyPoint &kp1 = keypoints1[i1], &kp2 = keypoints2[i2]; 213 _drawMatch( outImg, outImg1, outImg2, kp1, kp2, matchColor, flags ); 214 } 215 } 216} 217 218void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1, 219 InputArray img2, const std::vector<KeyPoint>& keypoints2, 220 const std::vector<std::vector<DMatch> >& matches1to2, InputOutputArray outImg, 221 const Scalar& matchColor, const Scalar& singlePointColor, 222 const std::vector<std::vector<char> >& matchesMask, int flags ) 223{ 224 if( !matchesMask.empty() && matchesMask.size() != matches1to2.size() ) 225 CV_Error( Error::StsBadSize, "matchesMask must have the same size as matches1to2" ); 226 227 Mat outImg1, outImg2; 228 _prepareImgAndDrawKeypoints( img1, keypoints1, img2, keypoints2, 229 outImg, outImg1, outImg2, singlePointColor, flags ); 230 231 // draw matches 232 for( size_t i = 0; i < matches1to2.size(); i++ ) 233 { 234 for( size_t j = 0; j < matches1to2[i].size(); j++ ) 235 { 236 int i1 = matches1to2[i][j].queryIdx; 237 int i2 = matches1to2[i][j].trainIdx; 238 if( matchesMask.empty() || matchesMask[i][j] ) 239 { 240 const KeyPoint &kp1 = keypoints1[i1], &kp2 = keypoints2[i2]; 241 _drawMatch( outImg, outImg1, outImg2, kp1, kp2, matchColor, flags ); 242 } 243 } 244 } 245} 246} 247