SaliencyCalculation.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package
19  * @author
20  * @date
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 #include "SaliencyCalculation.h"
25 
26 
27 // IVT
28 #include <Calibration/Calibration.h>
29 #include <Image/ByteImage.h>
30 #include <Image/ImageProcessor.h>
31 
32 // stdlib
33 #include <cmath>
34 
36 
37 #include <omp.h>
38 
40 {
41 
42  void
43  FindLocalMaxima(const std::vector<Vec3d>& aPoints3D,
44  const std::vector<Vec2d>& aPointsInImage,
45  std::vector<Vec3d>& aMaxima,
46  const int nBinSizeInPx,
47  CByteImage* pMaximumnessImage)
48  {
49  const int nNumBinsX = OLP_IMG_WIDTH / nBinSizeInPx + 1;
50  const int nNumBinsY = OLP_IMG_HEIGHT / nBinSizeInPx + 1;
51  const int nNumBinsTotal = nNumBinsX * nNumBinsY;
52 
53  float* pAverageZ = new float[nNumBinsTotal];
54 
55  for (int i = 0; i < nNumBinsTotal; i++)
56  {
57  pAverageZ[i] = 0;
58  }
59 
60  int* pBinPointCounters = new int[nNumBinsTotal];
61 
62  for (int i = 0; i < nNumBinsTotal; i++)
63  {
64  pBinPointCounters[i] = 0;
65  }
66 
67  Vec3d* pBinMaxima = new Vec3d[nNumBinsTotal];
68 
69  for (int i = 0; i < nNumBinsTotal; i++)
70  {
71  Math3d::SetVec(pBinMaxima[i], 0, 0, 0);
72  }
73 
74  char* pBinMaximumnessValues = new char[nNumBinsTotal];
75 
76  for (int i = 0; i < nNumBinsTotal; i++)
77  {
78  pBinMaximumnessValues[i] = 0;
79  }
80 
81 
82  // distribute points into the grid, accumulate z values, save the maximal z value for each cell
83  int nIndexX, nIndexY, nIndex;
84  const float fBinSizeInv = 1.0f / nBinSizeInPx;
85 
86  for (size_t i = 0; i < aPoints3D.size(); i++)
87  {
88  nIndexX = (int)(aPointsInImage.at(i).x * fBinSizeInv);
89  nIndexY = (int)(aPointsInImage.at(i).y * fBinSizeInv);
90  nIndex = nIndexY * nNumBinsX + nIndexX;
91 
92  if (0 <= nIndex && nIndex < nNumBinsTotal)
93  {
94  pAverageZ[nIndex] += aPoints3D.at(i).z;
95  pBinPointCounters[nIndex]++;
96 
97  if (pBinMaxima[nIndex].z < aPoints3D.at(i).z)
98  {
99  Math3d::SetVec(pBinMaxima[nIndex], aPoints3D.at(i));
100  }
101  }
102  }
103 
104  for (int i = 0; i < nNumBinsTotal; i++)
105  {
106  if (pBinPointCounters[i] != 0)
107  {
108  pAverageZ[i] /= pBinPointCounters[i];
109  }
110  }
111 
112 
113  // calculate maximumness and suppress non-maximum cells
114  float* pBinMaximaTemp = new float[nNumBinsTotal];
115 
116  for (int i = 0; i < nNumBinsTotal; i++)
117  {
118  pBinMaximaTemp[i] = 0;
119  }
120 
121  const float fMinHeightDifference =
122  0.033 * sqrt(sqrt(nBinSizeInPx)) * OLP_TOLERANCE_CONCURRENT_MOTION;
123 
124  for (int i = 1; i < nNumBinsY - 1; i++)
125  {
126  for (int j = 1; j < nNumBinsX - 1; j++)
127  {
128  const float z = pAverageZ[i * nNumBinsX + j];
129  bool bMax = true;
130  int nMaximumnessValue = 0;
131 
132  for (int k = -1; k <= 1; k++)
133  {
134  for (int l = -1; l <= 1; l++)
135  {
136  const float z1 = pAverageZ[(i + k) * nNumBinsX + (j + l)];
137 
138  if ((z > z1 + fMinHeightDifference) && (z1 != 0))
139  {
140  nMaximumnessValue++;
141  }
142  else if (z1 > z)
143  {
144  bMax = false;
145  }
146  }
147  }
148 
149  if (bMax)
150  {
151  pBinMaximaTemp[i * nNumBinsX + j] = pAverageZ[i * nNumBinsX + j];
152  }
153  else
154  {
155  pBinMaximaTemp[i * nNumBinsX + j] = 0;
156  }
157 
158  pBinMaximumnessValues[i * nNumBinsX + j] = nMaximumnessValue;
159  }
160  }
161 
162  // return maxima points
163  for (int i = 0; i < nNumBinsTotal; i++)
164  {
165  if (pBinMaximaTemp[i] != 0)
166  {
167  aMaxima.push_back(pBinMaxima[i]);
168  }
169  }
170 
171  ARMARX_VERBOSE_S << aMaxima.size() << " maxima";
172 
173 
174  // draw maximumness image
175  for (int i = 0; i < nNumBinsY; i++)
176  {
177  for (int j = 0; j < nNumBinsX; j++)
178  {
179  //const int nValue = (pBinMaximumnessValues[i*nNumBinsX+j] > 4) ? 63*(pBinMaximumnessValues[i*nNumBinsX+j]-4) : 0;
180  const int nValue = 31 * pBinMaximumnessValues[i * nNumBinsX + j];
181 
182  for (int k = i * nBinSizeInPx; k < (i + 1) * nBinSizeInPx && k < OLP_IMG_HEIGHT;
183  k++)
184  {
185  for (int l = j * nBinSizeInPx; l < (j + 1) * nBinSizeInPx && l < OLP_IMG_WIDTH;
186  l++)
187  {
188  pMaximumnessImage->pixels[k * OLP_IMG_WIDTH + l] = nValue;
189  }
190  }
191  }
192  }
193 
194  delete[] pAverageZ;
195  delete[] pBinPointCounters;
196  delete[] pBinMaxima;
197  delete[] pBinMaximaTemp;
198  delete[] pBinMaximumnessValues;
199  }
200 
201  void
202  FindLocalMaxima(const std::vector<CHypothesisPoint*>& aPoints,
203  const Mat3d mCameraToWorldRotation,
204  const Vec3d vCameraToWorldTranslation,
205  const CCalibration* calibration,
206  std::vector<Vec3d>& aMaxima,
207  CByteImage* pMaximumnessImage,
208  const int nBinSizeInPx)
209  {
210  std::vector<Vec3d> aPointsTransformed;
211  aPointsTransformed.resize(aPoints.size());
212 
213  for (size_t i = 0; i < aPoints.size(); i++)
214  {
215  Math3d::MulMatVec(mCameraToWorldRotation,
216  aPoints.at(i)->vPosition,
217  vCameraToWorldTranslation,
218  aPointsTransformed.at(i));
219  }
220 
221  std::vector<Vec2d> aPointsInImage;
222  aPointsInImage.resize(aPoints.size());
223 
224  for (size_t i = 0; i < aPoints.size(); i++)
225  {
226  calibration->WorldToImageCoordinates(
227  aPoints.at(i)->vPosition, aPointsInImage.at(i), false);
228  }
229 
230  CByteImage* pMaximumnessImage1 =
231  new CByteImage(OLP_IMG_WIDTH, OLP_IMG_HEIGHT, CByteImage::eGrayScale);
233  aPointsTransformed, aPointsInImage, aMaxima, nBinSizeInPx, pMaximumnessImage1);
234  CByteImage* pMaximumnessImage2 =
235  new CByteImage(OLP_IMG_WIDTH, OLP_IMG_HEIGHT, CByteImage::eGrayScale);
237  aPointsTransformed, aPointsInImage, aMaxima, 2 * nBinSizeInPx, pMaximumnessImage2);
238  CByteImage* pMaximumnessImage3 =
239  new CByteImage(OLP_IMG_WIDTH, OLP_IMG_HEIGHT, CByteImage::eGrayScale);
241  aPointsTransformed, aPointsInImage, aMaxima, 4 * nBinSizeInPx, pMaximumnessImage3);
242  CByteImage* pMaximumnessImage4 =
243  new CByteImage(OLP_IMG_WIDTH, OLP_IMG_HEIGHT, CByteImage::eGrayScale);
245  aPointsTransformed, aPointsInImage, aMaxima, 8 * nBinSizeInPx, pMaximumnessImage4);
246 
247  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
248  {
249  pMaximumnessImage->pixels[i] =
250  (pMaximumnessImage1->pixels[i] + pMaximumnessImage2->pixels[i] +
251  pMaximumnessImage3->pixels[i] + pMaximumnessImage4->pixels[i]) /
252  4;
253  }
254 
255  // smooth result
256  for (int i = 0; i < 10; i++)
257  {
258  ImageProcessor::GaussianSmooth3x3(pMaximumnessImage, pMaximumnessImage1);
259  ImageProcessor::GaussianSmooth3x3(pMaximumnessImage1, pMaximumnessImage);
260  }
261 
262  //pMaximumnessImage->SaveToFile("/home/staff/schieben/datalog/maxness.bmp");
263 
264  Mat3d mRotInv;
265  Vec3d vTemp;
266  Math3d::Transpose(mCameraToWorldRotation, mRotInv);
267 
268  for (size_t i = 0; i < aMaxima.size(); i++)
269  {
270  Math3d::SubtractVecVec(aMaxima.at(i), vCameraToWorldTranslation, vTemp);
271  Math3d::MulMatVec(mRotInv, vTemp, aMaxima.at(i));
272  }
273 
274  //ARMARX_VERBOSE_S << "%ld maxima\n", aMaxima.size());
275  }
276 
277  CComplexNumber
279  {
280  CComplexNumber c = {a.r * b.r - a.i * b.i, a.i * b.r + a.r * b.i};
281  return c;
282  }
283 
284  CComplexNumber
285  ExpComplImagOnly(const float a)
286  {
287  CComplexNumber c = {cos(a), sin(a)};
288  return c;
289  }
290 
291  void
292  FourierTransformation(const CByteImage* pGrayImage, CComplexNumber* pTransformed)
293  {
296  CComplexNumber* pTempArray1 = new CComplexNumber[nWidth * nHeight];
297  CComplexNumber* pTempArray2 = new CComplexNumber[nWidth * nHeight];
298  CByteImage* pSmallerImage = new CByteImage(nWidth, nHeight, CByteImage::eGrayScale);
299  ImageProcessor::Resize(pGrayImage, pSmallerImage);
300 
301  for (int i = 0; i < nWidth * nHeight; i++)
302  {
303  pTempArray1[i].r = pSmallerImage->pixels[i];
304  pTempArray1[i].i = 0;
305  }
306 
307  const double fWidthInv = 1.0 / nWidth;
308  const double fHeightInv = 1.0 / nHeight;
309 
310 #pragma omp parallel for
311  for (int v = 0; v < nHeight; v++)
312  {
313  for (int u = 0; u < nWidth; u++)
314  {
315  CComplexNumber vTemp, vSum = {0, 0};
316 
317  for (int j = 0; j < nWidth; j++)
318  {
319  vTemp = MultCompl(pTempArray1[v * nWidth + j],
320  ExpComplImagOnly(-2 * M_PI * j * u * fWidthInv));
321  vSum.r += vTemp.r;
322  vSum.i += vTemp.i;
323  }
324 
325  pTempArray2[v * nWidth + u].r = fWidthInv * vSum.r;
326  pTempArray2[v * nWidth + u].i = fWidthInv * vSum.i;
327  }
328  }
329 
330 #pragma omp parallel for
331  for (int u = 0; u < nWidth; u++)
332  {
333  for (int v = 0; v < nHeight; v++)
334  {
335  CComplexNumber vTemp, vSum = {0, 0};
336 
337  for (int j = 0; j < nHeight; j++)
338  {
339  vTemp = MultCompl(pTempArray2[j * nWidth + u],
340  ExpComplImagOnly(-2 * M_PI * v * j * fHeightInv));
341  vSum.r += vTemp.r;
342  vSum.i += vTemp.i;
343  }
344 
345  pTempArray1[v * nWidth + u].r = fHeightInv * vSum.r;
346  pTempArray1[v * nWidth + u].i = fHeightInv * vSum.i;
347  }
348  }
349 
350  for (int i = 0; i < nWidth * nHeight; i++)
351  {
352  pTransformed[i].r =
353  sqrt(pTempArray1[i].r * pTempArray1[i].r + pTempArray1[i].i * pTempArray1[i].i);
354  pTransformed[i].i = atan2(pTempArray1[i].i, pTempArray1[i].r);
355  //pTransformed[i].r = pTempArray1[i].r;
356  //pTransformed[i].i = pTempArray1[i].i;
357  }
358 
359  float fMaxAbs = 0;
360  float fMinPhase = pTransformed[0].i;
361  float fMaxPhase = pTransformed[0].i;
362 
363  for (int i = 0; i < nWidth * nHeight; i++)
364  {
365  if (pTransformed[i].r > fMaxAbs)
366  {
367  fMaxAbs = pTransformed[i].r;
368  }
369 
370  if (pTransformed[i].i < fMinPhase)
371  {
372  fMinPhase = pTransformed[i].i;
373  }
374 
375  if (pTransformed[i].i > fMaxPhase)
376  {
377  fMaxPhase = pTransformed[i].i;
378  }
379  }
380 
381  const float fMaxAbsInv = 255.0f / logf(fMaxAbs + 1);
382  const float fPhaseDiffInv = 255.0f / (fMaxPhase - fMinPhase);
383 
384  CByteImage* pOutAbs = new CByteImage(nWidth, nHeight, CByteImage::eGrayScale);
385  CByteImage* pOutPhase = new CByteImage(nWidth, nHeight, CByteImage::eGrayScale);
386 
387  for (int i = 0; i < nWidth * nHeight; i++)
388  {
389  pOutAbs->pixels[i] = fMaxAbsInv * logf(pTransformed[i].r + 1);
390  pOutPhase->pixels[i] = fPhaseDiffInv * (pTransformed[i].i - fMinPhase);
391  }
392 
393  //pOutAbs->SaveToFile("/home/staff/schieben/datalog/ft-abs.bmp");
394  //pOutPhase->SaveToFile("/home/staff/schieben/datalog/ft-pha.bmp");
395  //pSmallerImage->SaveToFile("/home/staff/schieben/datalog/ft-orig.bmp");
396 
397  delete[] pTempArray1;
398  delete[] pTempArray2;
399  delete pOutAbs;
400  delete pOutPhase;
401  }
402 
403  void
404  InverseFourierTransformation(CComplexNumber* pTransformed, CByteImage* pGrayImage)
405  {
408  CComplexNumber* pTempArray1 = new CComplexNumber[nWidth * nHeight];
409  CComplexNumber* pTempArray2 = new CComplexNumber[nWidth * nHeight];
410 
411 
412  for (int i = 0; i < nWidth * nHeight; i++)
413  {
414  pTempArray1[i].r = pTransformed[i].r * cosf(pTransformed[i].i);
415  pTempArray1[i].i = pTransformed[i].r * sinf(pTransformed[i].i);
416  //pTempArray1[i].r = pTransformed[i].r;
417  //pTempArray1[i].i = pTransformed[i].i;
418  }
419 
420  const double fWidthInv = 1.0 / nWidth;
421  const double fHeightInv = 1.0 / nHeight;
422 
423 #pragma omp parallel for
424  for (int j = 0; j < nWidth; j++)
425  {
426  for (int i = 0; i < nHeight; i++)
427  {
428  CComplexNumber vTemp, vSum = {0, 0};
429 
430  for (int v = 0; v < nHeight; v++)
431  {
432  vTemp = MultCompl(pTempArray1[v * nWidth + j],
433  ExpComplImagOnly(2 * M_PI * i * v * fHeightInv));
434  vSum.r += vTemp.r;
435  vSum.i += vTemp.i;
436  }
437 
438  pTempArray2[i * nWidth + j].r = vSum.r;
439  pTempArray2[i * nWidth + j].i = vSum.i;
440  }
441  }
442 
443 #pragma omp parallel for
444  for (int i = 0; i < nHeight; i++)
445  {
446  for (int j = 0; j < nWidth; j++)
447  {
448  CComplexNumber vTemp, vSum = {0, 0};
449 
450  for (int u = 0; u < nWidth; u++)
451  {
452  vTemp = MultCompl(pTempArray2[i * nWidth + u],
453  ExpComplImagOnly(2 * M_PI * j * u * fWidthInv));
454  vSum.r += vTemp.r;
455  vSum.i += vTemp.i;
456  }
457 
458  pTempArray1[i * nWidth + j].r = vSum.r;
459  pTempArray1[i * nWidth + j].i = vSum.i;
460  }
461  }
462 
463  CByteImage* pSmallerImage = new CByteImage(nWidth, nHeight, CByteImage::eGrayScale);
464 
465  for (int i = 0; i < nWidth * nHeight; i++)
466  {
467  pSmallerImage->pixels[i] =
468  (pTempArray1[i].r < 0) ? 0 : ((pTempArray1[i].r > 255) ? 255 : pTempArray1[i].r);
469  //pSmallerImage->pixels[i] = pTempArray1[i].i;
470  }
471 
472  ImageProcessor::Resize(pSmallerImage, pGrayImage);
473  //pGrayImage->SaveToFile("/home/staff/schieben/datalog/ft-restored.bmp");
474 
475  delete pSmallerImage;
476  delete[] pTempArray1;
477  delete[] pTempArray2;
478  }
479 
480  void
482  {
485 
486  double* pTempArray1 = new double[nWidth * nHeight];
487  double* pTempArray2 = new double[nWidth * nHeight];
488 
489  for (int i = 0; i < nWidth * nHeight; i++)
490  {
491  pTempArray1[i] = log(pTransformed[i].r);
492  }
493 
494  // average filter
495  const double fFactor1 = 0.12;
496  const double fFactor2 = 0.11;
497  const double fFactor3 = 0.11;
498 
499  for (int i = 1; i < nHeight - 1; i++)
500  {
501  for (int j = 1; j < nWidth - 1; j++)
502  {
503  pTempArray2[i * nWidth + j] = fFactor3 * pTempArray1[(i - 1) * nWidth + j - 1] +
504  fFactor2 * pTempArray1[(i - 1) * nWidth + j] +
505  fFactor3 * pTempArray1[(i - 1) * nWidth + j + 1] +
506  fFactor2 * pTempArray1[i * nWidth + j - 1] +
507  fFactor1 * pTempArray1[i * nWidth + j] +
508  fFactor2 * pTempArray1[i * nWidth + j + 1] +
509  fFactor3 * pTempArray1[(i + 1) * nWidth + j - 1] +
510  fFactor2 * pTempArray1[(i + 1) * nWidth + j] +
511  fFactor3 * pTempArray1[(i + 1) * nWidth + j + 1];
512  }
513  }
514 
515  // image borders
516  for (int i = 0; i < nWidth; i++)
517  {
518  pTempArray2[i] = pTempArray1[i];
519  pTempArray2[(nHeight - 1) * nWidth + i] = pTempArray1[(nHeight - 1) * nWidth + i];
520  }
521 
522  for (int i = 0; i < nHeight; i++)
523  {
524  pTempArray2[i * nWidth] = pTempArray1[i * nWidth];
525  pTempArray2[i * nWidth + nWidth - 1] = pTempArray1[i * nWidth + nWidth - 1];
526  }
527 
528 
529  for (int i = 0; i < nWidth * nHeight; i++)
530  {
531  pTransformed[i].r = exp(pTempArray1[i] - pTempArray2[i]);
532  }
533 
534  delete[] pTempArray1;
535  delete[] pTempArray2;
536  }
537 
538  void
539  FindSalientRegionsHou(const CByteImage* pImageRGB, CByteImage* pSaliencyImage)
540  {
541  CByteImage* pOneColorChannelImage =
542  new CByteImage(OLP_IMG_WIDTH, OLP_IMG_HEIGHT, CByteImage::eGrayScale);
543  int* pSaliencySum = new int[OLP_IMG_WIDTH * OLP_IMG_HEIGHT];
544 
545  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
546  {
547  pSaliencySum[i] = 0;
548  }
549 
550  for (int i = 0; i < 3; i++)
551  {
552  for (int j = 0; j < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; j++)
553  {
554  pOneColorChannelImage->pixels[j] = pImageRGB->pixels[3 * j + i];
555  }
556 
558  FourierTransformation(pOneColorChannelImage, pResult);
560  InverseFourierTransformation(pResult, pOneColorChannelImage);
561 
562  for (int j = 0; j < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; j++)
563  {
564  pSaliencySum[j] +=
565  pOneColorChannelImage->pixels[j] * pOneColorChannelImage->pixels[j];
566  }
567  }
568 
569  int nMin = pSaliencySum[0], nMax = pSaliencySum[0];
570 
571  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
572  {
573  if (pSaliencySum[i] < nMin)
574  {
575  nMin = pSaliencySum[i];
576  }
577 
578  if (pSaliencySum[i] > nMax)
579  {
580  nMax = pSaliencySum[i];
581  }
582  }
583 
584  const double fFactor = 255.0 / (nMax - nMin);
585 
586  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
587  {
588  pSaliencyImage->pixels[i] = fFactor * (pSaliencySum[i] - nMin);
589  }
590 
591  const float fSigma = 3;
592  const int nKernelSize = 4 * fSigma + 2; // >= 4*fSigma+1
593  ImageProcessor::GaussianSmooth(
594  pSaliencyImage, pSaliencyImage, fSigma * fSigma, nKernelSize);
595 
596  //pSaliencyImage->SaveToFile("/home/staff/schieben/datalog/ft-saliency.bmp");
597 
598  delete pOneColorChannelImage;
599  delete[] pSaliencySum;
600  }
601 
602  void
603  FindSalientRegionsAchanta(const CByteImage* pImageRGB, CByteImage* pSaliencyImage)
604  {
605  CByteImage* pImageLab = new CByteImage(OLP_IMG_WIDTH, OLP_IMG_HEIGHT, CByteImage::eRGB24);
606  CByteImage* pImageHSV = new CByteImage(OLP_IMG_WIDTH, OLP_IMG_HEIGHT, CByteImage::eRGB24);
607 
608 #pragma omp sections
609  {
610 #pragma omp section
611  {
612  ConvertRGB2Lab(pImageRGB, pImageLab);
613  }
614 
615 #pragma omp section
616  {
617  ImageProcessor::CalculateHSVImage(pImageRGB, pImageHSV);
618  }
619  }
620 
621  const int nNumChannels = 9;
622  int* pAllColorChannels = new int[nNumChannels * OLP_IMG_WIDTH * OLP_IMG_HEIGHT];
623 
624 #pragma omp parallel for
625  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
626  {
627  pAllColorChannels[nNumChannels * i] = pImageRGB->pixels[3 * i];
628  pAllColorChannels[nNumChannels * i + 1] = pImageRGB->pixels[3 * i + 1];
629  pAllColorChannels[nNumChannels * i + 2] = pImageRGB->pixels[3 * i + 2];
630 
631  pAllColorChannels[nNumChannels * i + 3] = pImageHSV->pixels[3 * i];
632  pAllColorChannels[nNumChannels * i + 4] = pImageHSV->pixels[3 * i + 1];
633  pAllColorChannels[nNumChannels * i + 5] = pImageHSV->pixels[3 * i + 1];
634 
635  pAllColorChannels[nNumChannels * i + 6] = pImageLab->pixels[3 * i];
636  pAllColorChannels[nNumChannels * i + 7] = pImageLab->pixels[3 * i + 1];
637  pAllColorChannels[nNumChannels * i + 8] = pImageLab->pixels[3 * i + 2];
638  }
639 
640  int* pSaliencySum = new int[OLP_IMG_WIDTH * OLP_IMG_HEIGHT];
641 
642  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
643  {
644  pSaliencySum[i] = 0;
645  }
646 
647  const int nParallelityFactor = omp_get_num_procs();
648  omp_set_num_threads(nParallelityFactor);
649  CByteImage** pOneColorChannelImages = new CByteImage*[nParallelityFactor];
650  CByteImage** pSmoothedImages = new CByteImage*[nParallelityFactor];
651  CByteImage** pExtremelySmoothedImages = new CByteImage*[nParallelityFactor];
652 
653  for (int i = 0; i < nParallelityFactor; i++)
654  {
655  pOneColorChannelImages[i] =
656  new CByteImage(OLP_IMG_WIDTH, OLP_IMG_HEIGHT, CByteImage::eGrayScale);
657  pSmoothedImages[i] =
658  new CByteImage(OLP_IMG_WIDTH, OLP_IMG_HEIGHT, CByteImage::eGrayScale);
659  pExtremelySmoothedImages[i] =
660  new CByteImage(OLP_IMG_WIDTH, OLP_IMG_HEIGHT, CByteImage::eGrayScale);
661  }
662 
663  const float fSigma1 = 80; // 60
664  const float fSigma2 = 10;
665  const int nKernelSize1 = 4 * fSigma1 + 1; // >= 4*fSigma+1
666  const int nKernelSize2 = 4 * fSigma2 + 1;
667 
668 #pragma omp parallel for
669  for (int i = 0; i < nNumChannels; i++)
670  {
671  const int nThreadNumber = omp_get_thread_num();
672 
673  //long nSum = 0;
674  for (int j = 0; j < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; j++)
675  {
676  pOneColorChannelImages[nThreadNumber]->pixels[j] =
677  pAllColorChannels[nNumChannels * j + i];
678  //nSum += pImageLab->pixels[nNumChannels*j+i];
679  }
680 
681  //int nAverage = nSum/(OLP_IMG_WIDTH*OLP_IMG_HEIGHT);
682 
683  ImageProcessor::GaussianSmooth(pOneColorChannelImages[nThreadNumber],
684  pExtremelySmoothedImages[nThreadNumber],
685  fSigma1 * fSigma1,
686  nKernelSize1);
687 
688  ImageProcessor::GaussianSmooth(pOneColorChannelImages[nThreadNumber],
689  pSmoothedImages[nThreadNumber],
690  fSigma2 * fSigma2,
691  nKernelSize2);
692 
693 #pragma omp critical
694  for (int j = 0; j < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; j++)
695  {
696  pSaliencySum[j] += (pExtremelySmoothedImages[nThreadNumber]->pixels[j] -
697  pSmoothedImages[nThreadNumber]->pixels[j]) *
698  (pExtremelySmoothedImages[nThreadNumber]->pixels[j] -
699  pSmoothedImages[nThreadNumber]->pixels[j]);
700  //pSaliencySum[j] += (nAverage-pSmoothedImage->pixels[j])*(nAverage-pSmoothedImage->pixels[j]);
701  }
702  }
703 
704 #pragma omp parallel for
705  for (int j = 0; j < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; j++)
706  {
707  pSaliencySum[j] = sqrt(pSaliencySum[j]);
708  }
709 
710 
711  // normalization
712  int nMin = pSaliencySum[0], nMax = pSaliencySum[0];
713 
714  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
715  {
716  if (pSaliencySum[i] < nMin)
717  {
718  nMin = pSaliencySum[i];
719  }
720 
721  if (pSaliencySum[i] > nMax)
722  {
723  nMax = pSaliencySum[i];
724  }
725  }
726 
727  const double fFactor = (nMax > nMin) ? 255.0 / (nMax - nMin) : 1.0;
728 
729 #pragma omp parallel for
730  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
731  {
732  pSaliencyImage->pixels[i] = fFactor * (pSaliencySum[i] - nMin);
733  }
734 
735  //ImageProcessor::GaussianSmooth5x5(pSaliencyImage, pSaliencyImage);
736 
737  //pSaliencyImage->SaveToFile("/home/staff/schieben/datalog/saliency.bmp");
738 
739  delete pImageLab;
740  delete pImageHSV;
741  delete[] pAllColorChannels;
742 
743  for (int i = 0; i < nParallelityFactor; i++)
744  {
745  delete pOneColorChannelImages[i];
746  delete pSmoothedImages[i];
747  delete pExtremelySmoothedImages[i];
748  }
749 
750  delete[] pOneColorChannelImages;
751  delete[] pSmoothedImages;
752  delete[] pExtremelySmoothedImages;
753  }
754 
755  void
756  ConvertRGB2Lab(const CByteImage* pImageRGB, CByteImage* pImageLab)
757  {
758  double r, g, b;
759  double x, y, z;
760  double L, A, B;
761  const double xn = 0.95;
762  const double yn = 1;
763  const double zn = 1.09;
764  const double dOneThird = 1.0 / 3.0;
765 
766  for (int i = 0; i < OLP_IMG_WIDTH * OLP_IMG_HEIGHT; i++)
767  {
768  r = pImageRGB->pixels[3 * i];
769  g = pImageRGB->pixels[3 * i + 1];
770  b = pImageRGB->pixels[3 * i + 2];
771  x = 0.4124564 * r + 0.3575761 * g + 0.1804375 * b;
772  y = 0.2126729 * r + 0.7151522 * g + 0.0721750 * b;
773  z = 0.0193339 * r + 0.1191920 * g + 0.9503041 * b;
774  L = 116 * pow(y / yn, dOneThird) - 16;
775  A = 500 * (pow(x / xn, dOneThird) - pow(y / yn, dOneThird));
776  B = 200 * (pow(y / yn, dOneThird) - pow(z / zn, dOneThird));
777  pImageLab->pixels[3 * i] = L;
778  pImageLab->pixels[3 * i + 1] = A + 150;
779  pImageLab->pixels[3 * i + 2] = B + 100;
780  }
781  }
782 
783 
784 } // namespace CSaliencyCalculation
OLP_IMG_HEIGHT
#define OLP_IMG_HEIGHT
Definition: ObjectLearningByPushingDefinitions.h:69
GfxTL::Vec3d
VectorXD< 3, double > Vec3d
Definition: VectorXD.h:737
OLP_IMG_WIDTH
#define OLP_IMG_WIDTH
Definition: ObjectLearningByPushingDefinitions.h:68
OLP_FOURIER_TRANSFORM_SCALING_FACTOR
#define OLP_FOURIER_TRANSFORM_SCALING_FACTOR
Definition: ObjectLearningByPushingDefinitions.h:226
CSaliencyCalculation::ExpComplImagOnly
CComplexNumber ExpComplImagOnly(const float a)
Definition: SaliencyCalculation.cpp:285
CSaliencyCalculation::CComplexNumber::r
double r
Definition: SaliencyCalculation.h:48
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
CSaliencyCalculation::FourierTransformation
void FourierTransformation(const CByteImage *pGrayImage, CComplexNumber *pTransformed)
Definition: SaliencyCalculation.cpp:292
CSaliencyCalculation::ConvertRGB2Lab
void ConvertRGB2Lab(const CByteImage *pImageRGB, CByteImage *pImageLab)
Definition: SaliencyCalculation.cpp:756
CSaliencyCalculation::SubstractAveragedLogPowerSpectrum
void SubstractAveragedLogPowerSpectrum(CComplexNumber *pTransformed)
Definition: SaliencyCalculation.cpp:481
CSaliencyCalculation::InverseFourierTransformation
void InverseFourierTransformation(CComplexNumber *pTransformed, CByteImage *pGrayImage)
Definition: SaliencyCalculation.cpp:404
CSaliencyCalculation::FindSalientRegionsAchanta
void FindSalientRegionsAchanta(const CByteImage *pImageRGB, CByteImage *pSaliencyImage)
Definition: SaliencyCalculation.cpp:603
CSaliencyCalculation::MultCompl
CComplexNumber MultCompl(const CComplexNumber a, const CComplexNumber b)
Definition: SaliencyCalculation.cpp:278
armarx::ctrlutil::a
double a(double t, double a0, double j)
Definition: CtrlUtil.h:45
M_PI
#define M_PI
Definition: MathTools.h:17
CSaliencyCalculation::FindLocalMaxima
void FindLocalMaxima(const std::vector< Vec3d > &aPoints3D, const std::vector< Vec2d > &aPointsInImage, std::vector< Vec3d > &aMaxima, const int nBinSizeInPx, CByteImage *pMaximumnessImage)
Definition: SaliencyCalculation.cpp:43
OLP_TOLERANCE_CONCURRENT_MOTION
#define OLP_TOLERANCE_CONCURRENT_MOTION
Definition: ObjectLearningByPushingDefinitions.h:238
CSaliencyCalculation::CComplexNumber
Definition: SaliencyCalculation.h:46
A
class A(deque< T, A >)) ARMARX_OVERLOAD_STD_HASH_FOR_ITERABLE((class T
Enables hashing of std::list.
GfxTL::sqrt
VectorXD< D, T > sqrt(const VectorXD< D, T > &a)
Definition: VectorXD.h:704
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
CSaliencyCalculation::CComplexNumber::i
double i
Definition: SaliencyCalculation.h:48
CSaliencyCalculation::FindSalientRegionsHou
void FindSalientRegionsHou(const CByteImage *pImageRGB, CByteImage *pSaliencyImage)
Definition: SaliencyCalculation.cpp:539
ARMARX_VERBOSE_S
#define ARMARX_VERBOSE_S
Definition: Logging.h:207
Logging.h
SaliencyCalculation.h
CSaliencyCalculation
Definition: SaliencyCalculation.cpp:39