ImageTools.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. #include "core/image/ImageTools.h"
  2. #include <math.h>
  3. #include <list>
  4. #include <vector>
  5. #include <queue>
  6. using namespace std;
  7. using namespace std;
  8. namespace NICE
  9. {
  10. // // // // // arithmetic an logical operations // // // // /
  11. Image* absDiff ( const Image& src0, const Image& src1, Image* dst )
  12. {
  13. if ( src0.width() != src1.width() || src0.height() != src0.height() )
  14. fthrow ( ImageException, "Source Images must have the same size." );
  15. Image *result = createResultBuffer ( src0.width(), src0.height(), dst );
  16. #ifdef NICE_USELIB_IPP
  17. IppStatus ret = ippiAbsDiff_8u_C1R ( src0.getPixelPointer(),
  18. src0.getStepsize(), src1.getPixelPointer(), src1.getStepsize(),
  19. result->getPixelPointer(), result->getStepsize(), makeROIFullImage (
  20. src0 ) );
  21. if ( ret != ippStsNoErr )
  22. fthrow ( ImageException, ippGetStatusString ( ret ) );
  23. #else // NICE_USELIB_IPP
  24. const Ipp8u* pSrc0Start = src0.getPixelPointer();
  25. const Ipp8u* pSrc1Start = src1.getPixelPointer();
  26. Ipp8u* pDstStart = result->getPixelPointer();
  27. const Ipp8u *pSrc0, *pSrc1;
  28. Ipp8u *pDst;
  29. for ( int y = 0; y < src0.height(); ++y )
  30. {
  31. pSrc0 = pSrc0Start;
  32. pSrc1 = pSrc1Start;
  33. pDst = pDstStart;
  34. for ( int x = 0; x < src0.width(); ++x, ++pSrc0, ++pSrc1, ++pDst )
  35. *pDst = std::abs ( *pSrc0 - *pSrc1 );
  36. pSrc0Start += src0.getStepsize();
  37. pSrc1Start += src1.getStepsize();
  38. pDstStart += result->getStepsize();
  39. }
  40. #endif // NICE_USELIB_IPP
  41. return ( result );
  42. }
  43. ColorImage* absDiff ( const ColorImage& src0, const ColorImage& src1,
  44. ColorImage* dst )
  45. {
  46. if ( src0.width() != src1.width() || src0.height() != src1.height() )
  47. fthrow ( ImageException, "Source Images must have the same size." );
  48. ColorImage *result = createResultBuffer ( src0.width(), src0.height(), dst );
  49. #ifdef NICE_USELIB_IPP
  50. IppiSize ippiSize =
  51. { src0.width() * 3, src0.height() };
  52. IppStatus ret = ippiAbsDiff_8u_C1R ( src0.getPixelPointer(),
  53. src0.getStepsize(), src1.getPixelPointer(), src1.getStepsize(),
  54. result->getPixelPointer(), result->getStepsize(), ippiSize );
  55. if ( ret != ippStsNoErr )
  56. fthrow ( ImageException, ippGetStatusString ( ret ) );
  57. #else // NICE_USELIB_IPP
  58. const Ipp8u* pSrc0Start = src0.getPixelPointer();
  59. const Ipp8u* pSrc1Start = src1.getPixelPointer();
  60. Ipp8u* pDstStart = result->getPixelPointer();
  61. const Ipp8u *pSrc0, *pSrc1;
  62. Ipp8u *pDst;
  63. for ( int y = 0; y < src0.height(); ++y )
  64. {
  65. pSrc0 = pSrc0Start;
  66. pSrc1 = pSrc1Start;
  67. pDst = pDstStart;
  68. for ( int x = 0; x < 3*src0.width(); ++x, ++pSrc0, ++pSrc1, ++pDst )
  69. *pDst = std::abs ( *pSrc0 - *pSrc1 );
  70. pSrc0Start += src0.getStepsize();
  71. pSrc1Start += src1.getStepsize();
  72. pDstStart += result->getStepsize();
  73. }
  74. #endif // NICE_USELIB_IPP
  75. return ( result );
  76. }
  77. Image* And ( const Image& src0, const Image& src1, Image *dst )
  78. {
  79. if ( src0.width() != src1.width() || src0.height() != src0.height() )
  80. fthrow ( ImageException, "Source Images must have the same size." );
  81. Image *result = createResultBuffer ( src0.width(), src0.height(), dst );
  82. #ifdef NICE_USELIB_IPP
  83. IppStatus ret = ippiAnd_8u_C1R ( src0.getPixelPointer(), src0.getStepsize(),
  84. src1.getPixelPointer(), src1.getStepsize(),
  85. result->getPixelPointer(), result->getStepsize(), makeROIFullImage (
  86. src0 ) );
  87. if ( ret != ippStsNoErr )
  88. fthrow ( ImageException, ippGetStatusString ( ret ) );
  89. #else // NICE_USELIB_IPP
  90. int bwidth = src0.width() / sizeof ( Ipp32u );
  91. int bwidthr = src0.width() - bwidth;
  92. for ( int y = 0; y < src0.height(); ++y )
  93. {
  94. const Ipp32u* s1 = ( const Ipp32u* ) ( src0.getPixelPointerY ( y ) );
  95. const Ipp32u* s2 = ( const Ipp32u* ) ( src1.getPixelPointerY ( y ) );
  96. Ipp32u* d = ( Ipp32u* ) ( result->getPixelPointerY ( y ) );
  97. for ( int x = 0; x < bwidth; ++x, ++s1, ++s2, ++d )
  98. *d = *s1 & *s2;
  99. const Ipp8u *ps1 = ( const Ipp8u* ) ( --s1 );
  100. const Ipp8u *ps2 = ( const Ipp8u* ) ( --s2 );
  101. Ipp8u *pd = ( Ipp8u* ) ( --d );
  102. for ( int x = 0; x < bwidthr; ++x, ++ps1, ++ps2, ++pd )
  103. *pd = *ps1 & *ps2;
  104. }
  105. #endif // NICE_USELIB_IPP
  106. return ( result );
  107. }
  108. ColorImage* And ( const ColorImage& src0, const ColorImage& src1, ColorImage* dst )
  109. {
  110. if ( src0.width() != src1.width() || src0.height() != src0.height() )
  111. fthrow ( ImageException, "Source Images must have the same size." );
  112. ColorImage *result = createResultBuffer ( src0.width(), src0.height(), dst );
  113. #ifdef NICE_USELIB_IPP
  114. IppStatus ret = ippiAnd_8u_C3R ( src0.getPixelPointer(), src0.getStepsize(),
  115. src1.getPixelPointer(), src1.getStepsize(),
  116. result->getPixelPointer(), result->getStepsize(), makeROIFullImage (
  117. src0 ) );
  118. if ( ret != ippStsNoErr )
  119. fthrow ( ImageException, ippGetStatusString ( ret ) );
  120. #else // NICE_USELIB_IPP
  121. int bwidth = ( src0.width() * 3 ) / sizeof ( Ipp32u );
  122. int bwidthr = ( src0.width() * 3 ) - bwidth;
  123. for ( int y = 0; y < src0.height(); ++y )
  124. {
  125. const Ipp32u* s1 = ( const Ipp32u* ) ( src0.getPixelPointerY ( y ) );
  126. const Ipp32u* s2 = ( const Ipp32u* ) ( src1.getPixelPointerY ( y ) );
  127. Ipp32u* d = ( Ipp32u* ) ( result->getPixelPointerY ( y ) );
  128. for ( int x = 0; x < bwidth; ++x, ++s1, ++s2, ++d )
  129. *d = *s1 & *s2;
  130. const Ipp8u *ps1 = ( const Ipp8u* ) ( --s1 );
  131. const Ipp8u *ps2 = ( const Ipp8u* ) ( --s2 );
  132. Ipp8u *pd = ( Ipp8u* ) ( --d );
  133. for ( int x = 0; x < bwidthr; ++x, ++ps1, ++ps2, ++pd )
  134. *pd = *ps1 & *ps2;
  135. }
  136. #endif // NICE_USELIB_IPP
  137. return ( result );
  138. }
  139. // // // // // threshold functions // // // // //
  140. Image* threshold ( const Image& src, const int threshold, Image* dst )
  141. {
  142. Image* result = createResultBuffer ( src, dst );
  143. #ifdef NICE_USELIB_IPP
  144. IppiSize roiSize =
  145. { src.width(), src.height() };
  146. IppStatus ret = ippiThreshold_Val_8u_C1R ( src.getPixelPointer(),
  147. src.getStepsize(), result->getPixelPointer(),
  148. result->getStepsize(), makeROIFullImage ( src ), threshold + 1, 0,
  149. ippCmpLess );
  150. if ( ret != ippStsNoErr )
  151. fthrow ( ImageException, ippGetStatusString ( ret ) );
  152. ret = ippiThreshold_Val_8u_C1R ( result->getPixelPointer(),
  153. result->getStepsize(), result->getPixelPointer(),
  154. result->getStepsize(), roiSize, threshold, 255, ippCmpGreater );
  155. if ( ret != ippStsNoErr )
  156. fthrow ( ImageException, ippGetStatusString ( ret ) );
  157. #else // NICE_USELIB_IPP
  158. const Ipp8u* pSrcStart = src.getPixelPointer();
  159. Ipp8u* pDstStart = result->getPixelPointer();
  160. const Ipp8u* pSrc;
  161. Ipp8u* pDst;
  162. for ( int y = 0; y < src.height(); ++y )
  163. {
  164. pSrc = pSrcStart;
  165. pDst = pDstStart;
  166. for ( int x = 0; x < src.width(); ++x, ++pSrc, ++pDst )
  167. *pDst = ( *pSrc > threshold ) ? 255 : 0;
  168. pSrcStart += src.getStepsize();
  169. pDstStart += result->getStepsize();
  170. }
  171. #endif
  172. return result;
  173. }
  174. Image* lowerThreshold ( const Image& src, const int threshold, Image* dst,
  175. const int value )
  176. {
  177. Image* result = createResultBuffer ( src, dst );
  178. #ifdef NICE_USELIB_IPP
  179. IppStatus ret = ippiThreshold_Val_8u_C1R ( src.getPixelPointer(),
  180. src.getStepsize(), result->getPixelPointer(),
  181. result->getStepsize(), makeROIFullImage ( src ), threshold + 1, value,
  182. ippCmpLess );
  183. if ( ret != ippStsNoErr )
  184. fthrow ( ImageException, ippGetStatusString ( ret ) );
  185. #else // NICE_USELIB_IPP
  186. const Ipp8u* pSrcStart = src.getPixelPointer();
  187. Ipp8u* pDstStart = result->getPixelPointer();
  188. const Ipp8u* pSrc;
  189. Ipp8u* pDst;
  190. for ( int y = 0; y < src.height(); ++y )
  191. {
  192. pSrc = pSrcStart;
  193. pDst = pDstStart;
  194. for ( int x = 0; x < src.width(); ++x, ++pSrc, ++pDst )
  195. *pDst = ( *pSrc <= threshold ) ? value : *pSrc;
  196. pSrcStart += src.getStepsize();
  197. pDstStart += result->getStepsize();
  198. }
  199. #endif
  200. return result;
  201. }
  202. Image* upperThreshold ( Image& src, const int threshold, Image* dst,
  203. const int value )
  204. {
  205. Image* result = createResultBuffer ( src, dst );
  206. #ifdef NICE_USELIB_IPP
  207. IppStatus ret = ippiThreshold_Val_8u_C1R ( src.getPixelPointer(),
  208. src.getStepsize(), result->getPixelPointer(),
  209. result->getStepsize(), makeROIFullImage ( src ), threshold, value,
  210. ippCmpGreater );
  211. if ( ret != ippStsNoErr )
  212. fthrow ( ImageException, ippGetStatusString ( ret ) );
  213. #else // NICE_USELIB_IPP
  214. const Ipp8u* pSrcStart = src.getPixelPointer();
  215. Ipp8u* pDstStart = result->getPixelPointer();
  216. const Ipp8u* pSrc;
  217. Ipp8u* pDst;
  218. for ( int y = 0; y < src.height(); ++y )
  219. {
  220. pSrc = pSrcStart;
  221. pDst = pDstStart;
  222. for ( int x = 0; x < src.width(); ++x, ++pSrc, ++pDst )
  223. *pDst = ( *pSrc > threshold ) ? value : *pSrc;
  224. pSrcStart += src.getStepsize();
  225. pDstStart += result->getStepsize();
  226. }
  227. #endif
  228. return result;
  229. }
  230. void thresholdIP ( Image& src, const int threshold )
  231. {
  232. #ifdef NICE_USELIB_IPP
  233. IppStatus ret = ippiThreshold_Val_8u_C1IR ( src.getPixelPointer(),
  234. src.getStepsize(), makeROIFullImage ( src ), threshold + 1, 0,
  235. ippCmpLess );
  236. if ( ret != ippStsNoErr )
  237. fthrow ( ImageException, ippGetStatusString ( ret ) );
  238. ret = ippiThreshold_Val_8u_C1IR ( src.getPixelPointer(), src.getStepsize(),
  239. makeROIFullImage ( src ), threshold, 255, ippCmpGreater );
  240. if ( ret != ippStsNoErr )
  241. fthrow ( ImageException, ippGetStatusString ( ret ) );
  242. #else // NICE_USELIB_IPP
  243. Ipp8u* pSrcStart = src.getPixelPointer();
  244. Ipp8u* pSrc;
  245. for ( int y = 0; y < src.height(); ++y )
  246. {
  247. pSrc = pSrcStart;
  248. for ( int x = 0; x < src.width(); ++x, ++pSrc )
  249. *pSrc = ( *pSrc <= threshold ) ? 0 : 255;
  250. pSrcStart += src.getStepsize();
  251. }
  252. #endif // NICE_USELIB_IPP
  253. }
  254. void lowerThresholdIP ( Image& src, const int threshold, const int value )
  255. {
  256. #ifdef NICE_USELIB_IPP
  257. IppStatus ret = ippiThreshold_Val_8u_C1IR ( src.getPixelPointer(),
  258. src.getStepsize(), makeROIFullImage ( src ), threshold + 1, value,
  259. ippCmpLess );
  260. if ( ret != ippStsNoErr )
  261. fthrow ( ImageException, ippGetStatusString ( ret ) );
  262. #else // NICE_USELIB_IPP
  263. Ipp8u* pSrcStart = src.getPixelPointer();
  264. Ipp8u* pSrc;
  265. for ( int y = 0; y < src.height(); ++y )
  266. {
  267. pSrc = pSrcStart;
  268. for ( int x = 0; x < src.width(); ++x, ++pSrc )
  269. *pSrc = ( *pSrc <= threshold ) ? value : *pSrc;
  270. pSrcStart += src.getStepsize();
  271. }
  272. #endif // NICE_USELIB_IPP
  273. }
  274. void upperThresholdIP ( Image& src, const int threshold, const int value )
  275. {
  276. #ifdef NICE_USELIB_IPP
  277. IppStatus ret = ippiThreshold_Val_8u_C1IR ( src.getPixelPointer(),
  278. src.getStepsize(), makeROIFullImage ( src ), threshold, value,
  279. ippCmpGreater );
  280. if ( ret != ippStsNoErr )
  281. fthrow ( ImageException, ippGetStatusString ( ret ) );
  282. #else // NICE_USELIB_IPP
  283. Ipp8u* pSrcStart = src.getPixelPointer();
  284. Ipp8u* pSrc;
  285. for ( int y = 0; y < src.height(); ++y )
  286. {
  287. pSrc = pSrcStart;
  288. for ( int x = 0; x < src.width(); ++x, ++pSrc )
  289. *pSrc = ( *pSrc > threshold ) ? value : *pSrc;
  290. pSrcStart += src.getStepsize();
  291. }
  292. #endif // NICE_USELIB_IPP
  293. }
  294. // // // // // Line Segmentation // // // // //
  295. FloatImage* houghTransformLUT()
  296. {
  297. FloatImage* lut = new FloatImage ( 256, 3 );
  298. for ( int phi = 0; phi < 180; ++phi )
  299. {
  300. lut->setPixelQuick ( phi, 0, std::cos ( ( phi * M_PI ) / 180.0 ) );
  301. lut->setPixelQuick ( phi, 1, std::sin ( ( phi * M_PI ) / 180.0 ) );
  302. }
  303. for ( int i = 0; i < 256; ++i )
  304. lut->setPixelQuick ( i, 2, 8 * std::log ( static_cast<float> ( i ) ) );
  305. return lut;
  306. }
  307. IntMatrix* houghTransform ( const Image& gradStr, const Image& gradDir,
  308. const uint& noLines, const uint& gradThresh, const uint& soAreaDeg,
  309. const uint& soAreaDist, const uint& soBorder, const FloatImage* lut,
  310. const int diffAngle )
  311. {
  312. if ( gradStr.width() != gradDir.width() || gradStr.height()
  313. != gradDir.height() )
  314. fthrow ( ImageException, "Source Images must have the same size." );
  315. int isoAreaDeg = soAreaDeg;
  316. int isoAreaDist = soAreaDist;
  317. int isoBorder = soBorder;
  318. int diag = static_cast<int> ( std::sqrt ( static_cast<double> ( gradStr.width()
  319. * gradStr.width() + gradStr.height() * gradStr.height() ) ) );
  320. // building hough akku
  321. int tdist, tphi;
  322. ImageT<int> akku ( 2 * diag + 1, 180 );
  323. akku.set ( 0 );
  324. // use lut if specified
  325. if ( lut != NULL )
  326. {
  327. for ( int y = isoBorder; y < gradStr.height() - isoBorder; ++y )
  328. for ( int x = isoBorder; x < gradStr.width() - isoBorder; ++x )
  329. if ( gradStr.getPixelQuick ( x, y ) > gradThresh )
  330. for ( int phi = gradDir.getPixelQuick ( x, y ) - diffAngle; phi
  331. < gradDir.getPixelQuick ( x, y ) + diffAngle; ++phi )
  332. {
  333. if ( phi >= 180 )
  334. tphi = phi % 180;
  335. else if ( phi < 0 )
  336. tphi = 180 + phi;
  337. else
  338. tphi = phi;
  339. tdist = static_cast<int> ( x * lut->getPixelQuick ( tphi,
  340. 0 ) + y * lut->getPixelQuick ( tphi, 1 ) );
  341. akku ( tdist + diag, tphi )
  342. += static_cast<int> ( lut->getPixelQuick (
  343. gradStr.getPixelQuick ( x, y ), 2 ) );
  344. }
  345. }
  346. else
  347. {
  348. for ( int y = isoBorder; y < gradStr.height() - isoBorder; ++y )
  349. for ( int x = isoBorder; x < gradStr.width() - isoBorder; ++x )
  350. if ( gradStr.getPixelQuick ( x, y ) > gradThresh )
  351. for ( int phi = gradDir.getPixelQuick ( x, y ) - diffAngle; phi
  352. < gradDir.getPixelQuick ( x, y ) + diffAngle; ++phi )
  353. {
  354. if ( phi >= 180 )
  355. tphi = phi % 180;
  356. else if ( phi < 0 )
  357. tphi = 180 + phi;
  358. else
  359. tphi = phi;
  360. tdist = static_cast<int> ( x
  361. * cos ( ( tphi * M_PI ) / 180.0 ) + y * sin ( ( tphi
  362. * M_PI ) / 180.0 ) );
  363. akku ( tdist + diag, tphi ) += static_cast<int> ( 8
  364. * std::log ( float ( gradStr.getPixelQuick ( x, y ) ) ) );
  365. }
  366. }
  367. //
  368. std::vector<IntVector> L;
  369. int max_dist, max_phi, max_val, _d, _p;
  370. while ( L.size() < noLines )
  371. {
  372. max_val = max_phi = max_dist = 0;
  373. for ( int phi = 0; phi < 180; ++phi )
  374. for ( int dist = -diag; dist <= diag; ++dist )
  375. if ( akku.getPixelQuick ( dist + diag, phi ) > max_val )
  376. {
  377. max_phi = phi;
  378. max_dist = dist;
  379. max_val = akku.getPixelQuick ( max_dist + diag, max_phi );
  380. }
  381. if ( max_val == 0 )
  382. break;
  383. for ( int deg = -isoAreaDeg; deg <= isoAreaDeg; ++deg )
  384. for ( int dist = -isoAreaDist; dist <= isoAreaDist; ++dist )
  385. if ( ( max_dist + dist ) >= -diag && ( max_dist + dist ) <= diag )
  386. {
  387. _p = max_phi + deg;
  388. _d = max_dist + dist;
  389. _d = ( _p >= 180 || _p < 0 ) ? -_d : _d;
  390. _p = ( _p >= 180 ) ? _p - 180 : ( _p < 0 ? _p + 180 : _p );
  391. akku ( _d + diag, _p ) = 0;
  392. }
  393. int buffer[3] =
  394. { max_dist, max_phi, max_val };
  395. L.push_back ( IntVector ( buffer, 3 ) );
  396. }
  397. IntMatrix* rMat = new IntMatrix ( L.size(), 3 );
  398. for ( uint j = 0; j < L.size(); ++j )
  399. for ( int i = 0; i < 3; ++i )
  400. ( *rMat ) ( j, i ) = L[j][i];
  401. return rMat;
  402. }
  403. ;
  404. IntMatrix* houghTransform ( const Image& gradStr, const uint& noLines,
  405. const uint& gradThresh, const uint& soAreaDeg, const uint& soAreaDist,
  406. const uint& soBorder, const FloatImage* lut )
  407. {
  408. int isoAreaDeg = soAreaDeg;
  409. int isoAreaDist = soAreaDist;
  410. int isoBorder = soBorder;
  411. int width = gradStr.width();
  412. int height = gradStr.height();
  413. int diag = static_cast<int> ( std::sqrt ( static_cast<double> ( width * width
  414. + height * height ) ) );
  415. // building hough akku
  416. int tdist;
  417. ImageT<int> akku ( 2 * diag + 1, 180 );
  418. akku.set ( 0 );
  419. if ( lut != NULL )
  420. {
  421. for ( int y = isoBorder; y < gradStr.height() - isoBorder; ++y )
  422. for ( int x = isoBorder; x < gradStr.width() - isoBorder; ++x )
  423. if ( gradStr.getPixelQuick ( x, y ) > gradThresh )
  424. for ( int tphi = 0; tphi < 180; ++tphi )
  425. {
  426. tdist = static_cast<int> ( x * lut->getPixelQuick ( tphi,
  427. 0 ) + y * lut->getPixelQuick ( tphi, 1 ) );
  428. akku ( tdist + diag, tphi )
  429. += static_cast<int> ( lut->getPixelQuick (
  430. gradStr.getPixelQuick ( x, y ), 2 ) );
  431. }
  432. }
  433. else
  434. {
  435. for ( int y = isoBorder; y < gradStr.height() - isoBorder; ++y )
  436. for ( int x = isoBorder; x < gradStr.width() - isoBorder; ++x )
  437. if ( gradStr.getPixelQuick ( x, y ) > gradThresh )
  438. for ( int tphi = 0; tphi < 180; ++tphi )
  439. {
  440. tdist = static_cast<int> ( x
  441. * cos ( ( tphi * M_PI ) / 180.0 ) + y * sin ( ( tphi
  442. * M_PI ) / 180.0 ) );
  443. akku ( tdist + diag, tphi ) += static_cast<int> ( 8
  444. * std::log ( float ( gradStr.getPixelQuick ( x, y ) ) ) );
  445. }
  446. }
  447. //
  448. std::vector<IntVector> L;
  449. int max_dist, max_phi, max_val, _d, _p;
  450. while ( L.size() < noLines )
  451. {
  452. max_val = max_phi = max_dist = 0;
  453. for ( int phi = 0; phi < 180; ++phi )
  454. for ( int dist = -diag; dist <= diag; ++dist )
  455. if ( akku.getPixelQuick ( dist + diag, phi ) > max_val )
  456. {
  457. max_phi = phi;
  458. max_dist = dist;
  459. max_val = akku.getPixelQuick ( max_dist + diag, max_phi );
  460. }
  461. if ( max_val == 0 )
  462. break;
  463. for ( int deg = -isoAreaDeg; deg <= isoAreaDeg; ++deg )
  464. for ( int dist = -isoAreaDist; dist <= isoAreaDist; ++dist )
  465. if ( ( max_dist + dist ) >= -diag && ( max_dist + dist ) <= diag )
  466. {
  467. _p = max_phi + deg;
  468. _d = max_dist + dist;
  469. _d = ( _p >= 180 || _p < 0 ) ? -_d : _d;
  470. _p = ( _p >= 180 ) ? _p - 180 : ( _p < 0 ? _p + 180 : _p );
  471. akku ( _d + diag, _p ) = 0;
  472. }
  473. int buffer[3] =
  474. { max_dist, max_phi, max_val };
  475. L.push_back ( IntVector ( buffer, 3 ) );
  476. }
  477. IntMatrix* rMat = new IntMatrix ( L.size(), 3 );
  478. for ( uint j = 0; j < L.size(); ++j )
  479. for ( int i = 0; i < 3; ++i )
  480. ( *rMat ) ( j, i ) = L[j][i];
  481. return rMat;
  482. }
  483. // // // // // Corner Detection // // // // //
  484. Matrix* KLTCornerDetector ( const Image& src, const uint& noCorners,
  485. const double& EVThresh, const uint& soNeighborhood, const uint& soArea,
  486. const GrayImage16s* gradX, const GrayImage16s* gradY )
  487. {
  488. if ( gradX != NULL )
  489. if ( gradX->width() != src.width() || gradX->height() != src.height() )
  490. fthrow ( ImageException, "Optional gradient image gradY must have the same size like src." );
  491. if ( gradY != NULL )
  492. if ( gradY->width() != src.width() || gradY->height() != src.height() )
  493. fthrow ( ImageException, "Optional gradient image gradY must have the same size like src." );
  494. const GrayImage16s* diffX = ( gradX == NULL ) ? sobelX ( src ) : gradX;
  495. const GrayImage16s* diffY = ( gradY == NULL ) ? sobelY ( src ) : gradY;
  496. //
  497. uint EXQ, EYQ, EXY;
  498. double eigenV;
  499. int xval, yval;
  500. // std::vector is used because VectorT doesn't support something like push_back
  501. std::priority_queue<std::pair<double, std::pair<int, int> > > IP;
  502. for ( int y = soNeighborhood + 1; y < src.height() - 1
  503. - static_cast<int> ( soNeighborhood ); ++y )
  504. for ( int x = soNeighborhood + 1; x < src.width() - 1
  505. - static_cast<int> ( soNeighborhood ); ++x )
  506. {
  507. // build structure matrix for actuall pixel
  508. EXQ = EYQ = EXY = 0;
  509. for ( int tx = -static_cast<int> ( soNeighborhood ); tx
  510. <= static_cast<int> ( soNeighborhood ); ++tx )
  511. for ( int ty = -static_cast<int> ( soNeighborhood ); ty
  512. <= static_cast<int> ( soNeighborhood ); ++ty )
  513. {
  514. xval = ( *diffX ) ( x + tx, y + ty );
  515. yval = ( *diffY ) ( x + tx, y + ty );
  516. EXQ += xval * xval;
  517. EXY += xval * yval;
  518. EYQ += yval * yval;
  519. }
  520. // calc the smallest of the 2 eigenvalues of the char. matrix
  521. eigenV = ( EXQ + EYQ + sqrt ( static_cast<double> ( ( EXQ - EYQ ) * ( EXQ
  522. - EYQ ) + 4 * EXY * EXY ) ) );
  523. if ( eigenV > 0 && eigenV >= EVThresh )
  524. {
  525. IP.push ( pair<double, pair<int, int> > ( eigenV, pair<int, int> (
  526. x, y ) ) );
  527. }
  528. }
  529. if ( gradX == NULL )
  530. delete diffX;
  531. if ( gradY == NULL )
  532. delete diffY;
  533. Matrix* ipMat;
  534. if ( noCorners == 0 )
  535. {
  536. ipMat = new Matrix ( IP.size(), 3, 0 );
  537. }
  538. else
  539. {
  540. ipMat = new Matrix ( IP.size() < noCorners ? IP.size() : noCorners, 3, 0 );
  541. }
  542. Image markImg ( src.width(), src.height() );
  543. markImg.set ( 0 );
  544. Rect rect;
  545. for ( size_t c = 0; c < ipMat->rows(); ++c )
  546. {
  547. int xp, yp;
  548. double ev = -1.0;
  549. bool validCornerFound = false;
  550. do
  551. {
  552. const std::pair<double, std::pair<int, int> > & topElement =
  553. IP.top();
  554. xp = topElement.second.first;
  555. yp = topElement.second.second;
  556. if ( markImg.getPixelQuick ( xp, yp ) == 0 )
  557. {
  558. ev = topElement.first;
  559. validCornerFound = true;
  560. }
  561. IP.pop();
  562. } while ( !validCornerFound && !IP.empty() );
  563. if ( !validCornerFound )
  564. {
  565. ipMat->resize ( c, 3 );
  566. break;
  567. }
  568. ( *ipMat ) ( c, 0 ) = xp; // x-pos
  569. ( *ipMat ) ( c, 1 ) = yp; // y-pos
  570. ( *ipMat ) ( c, 2 ) = ev; // EV
  571. // mark area around this corner
  572. rect = Rect ( xp - static_cast<int> ( soArea / 2 ), yp
  573. - static_cast<int> ( soArea / 2 ), soArea, soArea );
  574. rect = clipRect ( markImg, rect );
  575. for ( int y = rect.top; y < rect.bottom(); ++y )
  576. for ( int x = rect.left; x < rect.right(); ++x )
  577. markImg.setPixelQuick ( x, y, 255 );
  578. }
  579. return ipMat;
  580. }
  581. }
  582. ; // namespace NICE