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