ImageTools.cpp 23 KB

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