00001 #ifndef Impala_Core_VideoSet_KfrMotionExtractor_h
00002 #define Impala_Core_VideoSet_KfrMotionExtractor_h
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "Core/VideoSet/Reporter.h"
00017 #include "Core/Vector/VectorTem.h"
00018 #include "Core/Feature/FeatureTable.h"
00019 #include "Core/Stream/SeqConvKernel.h"
00020 #include "Core/Array/RGB2Gray.h"
00021
00022
00023
00024
00025 #ifdef __BITMAP_FUNC__
00026 #include "Core/Feature/Bitmap.h"
00027 #endif
00028
00029
00030
00031 #define MVBLOCKSIZE 16
00032
00033 #define MAX_DISP 10
00034 #define TPL_NUM 3
00035
00036 #define BYTE unsigned char
00037 #define BOOL bool
00038 #define UINT unsigned int
00039
00040
00041 namespace Impala
00042 {
00043 namespace Core
00044 {
00045 namespace VideoSet
00046 {
00047
00048 class KfrMotionExtractor : public Listener
00049 {
00050
00051 protected:
00052
00053 typedef Vector::VectorTem<Real64> VectorReal64;
00054
00055 public:
00056
00057 KfrMotionExtractor(Reporter* reporter,
00058 CmdOptions& options, CString featureName, int binCount)
00059 {
00060 mReporter = reporter;
00061 mFeatureName = featureName;
00062 mBinCount = binCount;
00063 Feature::FeatureDefinition def(GetFeatureName());
00064 mHistogramTable = new Feature::FeatureTable(def, 1000, GetBinCount());
00065
00066 m_bNormalize = TRUE;
00067 m_verbose = FALSE;
00068 m_verbose2 = FALSE;
00069 }
00070
00071 KfrMotionExtractor(Reporter* reporter, CmdOptions& options)
00072 {
00073 mReporter = reporter;
00074 mFeatureName = "kfrmotion";
00075 mBinCount = 2 * TPL_NUM;
00076 Feature::FeatureDefinition def(GetFeatureName());
00077 mHistogramTable = new Feature::FeatureTable(def, 1000, GetBinCount());
00078
00079 m_bNormalize = TRUE;
00080
00081 m_verbose = FALSE;
00082 m_verbose2 = FALSE;
00083
00084
00085
00086 }
00087
00088 virtual
00089 ~KfrMotionExtractor()
00090 {
00091 }
00092
00093 String
00094 GetFeatureName() const
00095 {
00096 return mFeatureName;
00097 }
00098
00099 virtual void
00100 HandleNewFrame(VideoSet* vs, int fileId, Stream::RgbDataSrc* src)
00101 {
00102 if (!src)
00103 {
00104 ILOG_ERROR("Not a valid source for fileId " << fileId);
00105 return;
00106 }
00107
00108 Array::Array2dVec3UInt8* im = Array::ArrayCreate<Array::Array2dVec3UInt8>
00109 (src->FrameWidth(), src->FrameHeight(), 0, 0, src->DataPtr(), true);
00110 if (!im)
00111 {
00112 ILOG_ERROR("Couldn't load image for fileId " << fileId);
00113 return;
00114 }
00115
00116 if (m_verbose)
00117 {
00118 std::cout << "Current Frame No. = " << src->FrameNr() << std::endl;
00119 }
00120
00121 #ifdef __BITMAP_FUNC__
00122 Core::Feature::Bitmap bitmap;
00123 bitmap.SaveRgb2BitmapFile("test_rgb_00.bmp",src->DataPtr(), src->FrameWidth(), src->FrameHeight() );
00124 #endif
00125
00126
00127
00128
00129
00130 double feature[2*TPL_NUM];
00131 memset(feature,0,sizeof(double)*2*TPL_NUM);
00132
00133
00134
00135 typedef Stream::RgbDataSrcWindow<Stream::WindowPrepRgb2Ooo> WindowType;
00136 WindowType* window = dynamic_cast<WindowType*>(src);
00137 if (window)
00138 {
00139 if (m_verbose)
00140 {
00141 std::cout << "window size = " << window->WindowSize() << std::endl;
00142 }
00143
00144
00145
00146
00147
00148
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 int bWidth = window->FrameWidth()/MVBLOCKSIZE;
00172 int bHeight = window->FrameHeight()/MVBLOCKSIZE;
00173
00174
00175
00176
00177
00178 for (int t=0;t<TPL_NUM;t++)
00179 {
00180 m_Weight[t] = new double[bWidth * bHeight];
00181 memset(m_Weight[t], 0, sizeof(double)* bWidth * bHeight);
00182
00183 if (m_verbose2)
00184 {
00185 DumpWeightMatrix(m_Weight[t], bWidth, bHeight, t);
00186 }
00187 }
00188
00189 m_EnergyBuffer = new BYTE[bWidth * bHeight];
00190 m_EnergyMap = new double[bWidth * bHeight];
00191 m_Buffer = new BYTE[bWidth * bHeight * 2];
00192
00193
00194 LoadEnergyTemplate(bWidth, bHeight);
00195
00196
00197 CalcTPLMean(bWidth, bHeight);
00198
00199 m_MVseq = new BYTE[bWidth * bHeight * 2 * (window->WindowSize()-1)];
00200 memset(m_MVseq, 0, sizeof(BYTE)*bWidth * bHeight * 2 * (window->WindowSize()-1) );
00201
00202
00203
00204
00205
00206 for (int i=1 ; i<window->WindowSize() ; i++)
00207 {
00208
00209 Array::Array2dVec3UInt8* pre_rgb = Array::ArrayCreate<Array::Array2dVec3UInt8>
00210 (window->FrameWidth(), window->FrameHeight(), 0, 0, window->DataPtrWindow(i-1), true);
00211 if (!pre_rgb)
00212 {
00213 ILOG_ERROR("Couldn't load image for fileId " << fileId);
00214 return;
00215 }
00216
00217
00218 Array::Array2dVec3UInt8* cur_rgb = Array::ArrayCreate<Array::Array2dVec3UInt8>
00219 (window->FrameWidth(), window->FrameHeight(), 0, 0, window->DataPtrWindow(i), true);
00220 if (!cur_rgb)
00221 {
00222 ILOG_ERROR("Couldn't load image for fileId " << fileId);
00223 return;
00224 }
00225
00226 #ifdef __BITMAP_FUNC__
00227
00228
00229 #endif
00230
00231
00232 Array::Array2dScalarUInt8* pre = 0;
00233 Array::Array2dScalarUInt8* cur = 0;
00234 RGB2Gray(pre,pre_rgb);
00235 RGB2Gray(cur,cur_rgb);
00236
00237
00238 Int64 body = pre->BW() + pre->BH();
00239
00240 #ifdef __BITMAP_FUNC__
00241
00242
00243 #endif
00244 CalcMotionVectors((unsigned char*)pre->CPB(),(unsigned char*)cur->CPB(),window->FrameWidth(),window->FrameHeight(),m_MVseq, i-1);
00245
00246 if (m_verbose2) DumpMVF(m_MVseq, bWidth, bHeight, i-1);
00247
00248
00249 delete pre_rgb;
00250 delete cur_rgb;
00251 delete pre;
00252 delete cur;
00253
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 int result = ComputeEnergy(window->WindowSize()-1, bWidth, bHeight, m_MVseq, feature);
00266
00267 if (0 != result) return;
00268
00269 for (int i=0;i<TPL_NUM;i++)
00270 delete []m_Weight[i];
00271 delete []m_EnergyBuffer;
00272 delete []m_EnergyMap;
00273 delete []m_Buffer;
00274 delete []m_MVseq;
00275
00276 }
00277 delete im;
00278
00279 VectorReal64 mvfeature(2*TPL_NUM);
00280 for (int x=0; x<2*TPL_NUM; x++)
00281 {
00282 mvfeature[x] = feature[x];
00283 }
00284 Quid quid = vs->GetQuidFrame(fileId, src->FrameNr());
00285 mHistogramTable->Add(quid, mvfeature);
00286
00287 ILOG_DEBUG("... done keyframe " << src->FrameNr());
00288
00289 }
00290
00291 virtual void
00292 HandleDoneFile(VideoSet* vs, int fileId, Stream::RgbDataSrc* src)
00293 {
00294 bool binary = true;
00295 Feature::FeatureDefinition def = mHistogramTable->GetFeatureDefinition();
00296
00297
00298 std::string fName = vs->GetFilePathFeatureData("Keyframes", def, fileId, false, -1, true, false);
00299
00300 if (!fName.empty())
00301 Table::Write(mHistogramTable, fName, vs->GetDatabase(), binary);
00302 mHistogramTable->SetSize(0);
00303 }
00304
00305
00306 void DumpMVFseq(BYTE* mvseq, int bWidth, int bHeight, int N)
00307 {
00308
00309
00310 for (int w=0; w<N; w++)
00311 {
00312 printf("MVF (%dx%d) for window %d:\n",bWidth,bHeight,w);
00313 for (int j=0; j<bHeight; j++)
00314 {
00315 for (int i=0; i<bWidth; i++)
00316 {
00317 BYTE sx = mvseq[sizeof(BYTE)*bWidth*bHeight*2* w + (j*bWidth + i)*2 +0];
00318 BYTE sy = mvseq[sizeof(BYTE)*bWidth*bHeight*2* w + (j*bWidth + i)*2 +1];
00319 printf("(%d,%d) ",sx,sy);
00320 }
00321 printf("\n");
00322 }
00323 printf("\n");
00324 }
00325 }
00326
00327
00328 void DumpMVF(BYTE* mvseq, int bWidth, int bHeight, int index)
00329 {
00330 printf("MVF (%dx%d) for window %d:\n",bWidth,bHeight,index);
00331 for (int j=0; j<bHeight; j++)
00332 {
00333 for (int i=0; i<bWidth; i++)
00334 {
00335 BYTE sx = mvseq[sizeof(BYTE)*bWidth*bHeight*2* index + (j*bWidth + i)*2 +0];
00336 BYTE sy = mvseq[sizeof(BYTE)*bWidth*bHeight*2* index + (j*bWidth + i)*2 +1];
00337 printf("(%d,%d) ",sx,sy);
00338 }
00339 printf("\n");
00340 }
00341 printf("\n");
00342 }
00343
00344 void DumpEnergyMap(int bWidth, int bHeight, char* comments="")
00345 {
00346 printf("Energy Map (%dx%d): Window Index -> %s\n", bWidth, bHeight, comments);
00347 for (int j=0; j<bHeight; j++)
00348 {
00349 for (int i=0; i<bWidth; i++)
00350 {
00351 printf("%.1f ",m_EnergyMap[j*bWidth + i]);
00352 }
00353 printf("\n");
00354 }
00355 printf("\n");
00356 }
00357
00358 void DumpEnergyBuffer(int bWidth, int bHeight)
00359 {
00360 printf("Energy Buffer (%dx%d):\n",bWidth,bHeight);
00361 for (int j=0; j<bHeight; j++)
00362 {
00363 for (int i=0; i<bWidth; i++)
00364 {
00365 printf("%d ",m_EnergyBuffer[j*bWidth + i]);
00366 }
00367 printf("\n");
00368 }
00369 printf("\n");
00370 }
00371
00372
00373
00374
00375
00376 int ComputeEnergy(int WindowLen, int bWidth, int bHeight, BYTE* mvseq, double* feature, int CurBufSize = 5)
00377 {
00378 IsInShot = FALSE;
00379
00380
00381 OnShotStart(bWidth, bHeight);
00382
00383 for (int t=0; t<2*TPL_NUM; t++)
00384 {
00385 feature[t] = 0.0;
00386 }
00387
00388
00389 if (WindowLen < CurBufSize)
00390 {
00391 printf("Error: WindowLen (%d) is smaller than CurBufSize (%d)\n", WindowLen, CurBufSize);
00392 return 1;
00393 }
00394 int num = WindowLen - CurBufSize;
00395 for (int index = 0; index < 1+num; index++)
00396 {
00397
00398 FillBuffer(CurBufSize, bWidth, bHeight, mvseq + sizeof(BYTE)*bWidth*bHeight*2*index);
00399
00400 int i=0;
00401 float Temp1Energy[TPL_NUM];
00402 float Temp2Energy[TPL_NUM];
00403 float diffEnergy[TPL_NUM];
00404 memset(diffEnergy,0,TPL_NUM*sizeof(float));
00405
00406 for (i=0;i<TPL_NUM;i++)
00407 {
00408
00409 float Energy = 0.0;
00410 if (m_bNormalize)
00411 {
00412 Energy = CalcEnergy(i, bWidth, bHeight);
00413 } else {
00414 Energy = CalcEnergy(i, bWidth, bHeight, FALSE);
00415 }
00416
00417
00418 if (index==0)
00419 Temp1Energy[i]=Energy;
00420 else if (index==1)
00421 Temp2Energy[i]=Energy;
00422 else
00423 {
00424 Temp1Energy[i] = Temp2Energy[i];
00425 Temp2Energy[i] = Energy;
00426 }
00427
00428 if (m_verbose) printf("%.5f\t", Energy);
00429
00430
00431 feature[i] += Energy;
00432 }
00433
00434
00435
00436
00437 if (index>0)
00438 {
00439 for (i=0;i<TPL_NUM;i++)
00440 {
00441 if (m_bNormalize)
00442 {
00443
00444 diffEnergy[i] = fabs(Temp2Energy[i] - Temp1Energy[i]);
00445
00446 } else {
00447 diffEnergy[i] = Temp2Energy[i] - Temp1Energy[i];
00448 }
00449
00450 if (m_verbose) printf("%.5f\t", diffEnergy[i]);
00451
00452
00453 feature[TPL_NUM+i] += diffEnergy[i];
00454
00455 }
00456 if (m_verbose) printf("\n");
00457
00458 } else {
00459
00460
00461 if (m_verbose) printf("diff1\tdiff2\tdiff3\n");
00462
00463 for (i=0;i<TPL_NUM;i++)
00464 {
00465
00466 feature[TPL_NUM+i] = 0.0;
00467 }
00468 }
00469 }
00470
00471 OnShotEnd(bWidth, bHeight);
00472
00473
00474 for (int t=0; t<TPL_NUM; t++)
00475 {
00476 feature[t] /= num+1;
00477 feature[TPL_NUM+t] /= num;
00478 }
00479
00480 if (m_verbose)
00481 {
00482 printf("\nThe Average as the final feature:\n");
00483 for (int t=0; t<2*TPL_NUM; t++)
00484 {
00485 printf("%.5f ",feature[t]);
00486 }
00487 printf("\n\n");
00488 }
00489
00490 return 0;
00491
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529 void LoadEnergyTemplate(int bWidth, int bHeight)
00530 {
00531 int i=0,j=0;
00532
00533
00534 int base = 1;
00535 int delta = 4;
00536 for (i=0; i<bWidth; i++)
00537 for (j=0; j<bHeight; j++)
00538 {
00539 m_Weight[0][j*bWidth+i] = base + delta*i;
00540 }
00541 m_TPLMin[0] = base;
00542 m_TPLMax[0] = base + delta*(bWidth-1);
00543
00544
00545 delta = 5;
00546 for (j=0; j<bHeight; j++)
00547 for (i=0; i<bWidth; i++)
00548 {
00549 m_Weight[1][j*bWidth+i] = base + delta*j;
00550 }
00551 m_TPLMin[1] = base;
00552 m_TPLMax[1] = base + delta*(bHeight-1);
00553
00554
00555 delta=16;
00556 int k=0;
00557 int dim = (bWidth<=bHeight) ? bWidth: bHeight;
00558 for (k=0; k<dim/2; k++)
00559 {
00560
00561 i=0+k;
00562 for (j=0+k; j<bHeight-k; j++)
00563 {
00564 m_Weight[2][j*bWidth+i] = base + delta*k;
00565 }
00566
00567
00568 i=bWidth-1-k;
00569 for (j=0+k; j<bHeight-k; j++)
00570 {
00571 m_Weight[2][j*bWidth+i] = base + delta*k;
00572 }
00573
00574
00575 j=0+k;
00576 for (i=0+k; i<bWidth-k; i++)
00577 {
00578 m_Weight[2][j*bWidth+i] = base + delta*k;
00579 }
00580
00581
00582 j=bHeight-1-k;
00583 for (i=0+k; i<bWidth-k; i++)
00584 {
00585 m_Weight[2][j*bWidth+i] = base + delta*k;
00586 }
00587
00588
00589
00590 }
00591
00592
00593
00594 m_TPLMin[2] = base;
00595 m_TPLMax[2] = base + delta*k;
00596 if (dim%2==1)
00597 {
00598 if (bWidth >= bHeight)
00599 {
00600
00601 j=0+k;
00602 for (i=0+k; i<bWidth-k; i++)
00603 {
00604 m_Weight[2][j*bWidth+i] = base + delta*k;
00605 }
00606 }
00607 else
00608 {
00609
00610 i=0+k;
00611 for (j=0+k; j<bHeight-k; j++)
00612 {
00613 m_Weight[2][j*bWidth+i] = base + delta*k;
00614 }
00615 }
00616
00617
00618 }
00619
00620
00621 if (m_verbose2)
00622 {
00623 for (int t=0;t<TPL_NUM;t++)
00624 {
00625 DumpWeightMatrix(m_Weight[t], bWidth, bHeight, t);
00626 }
00627 }
00628
00629 }
00630
00631 void DumpWeightMatrix(double* weight, int bWidth, int bHeight, int index)
00632 {
00633
00634 printf("Template Weigth Matrix (%dx%d)_%d is:\n",bWidth,bHeight, index);
00635
00636 int i,j;
00637 for (j=0; j<bHeight; j++)
00638 {
00639 for (i=0; i<bWidth; i++)
00640 {
00641 printf("%2.d ",(int)weight[j*bWidth+i]);
00642
00643 }
00644 printf("\n");
00645 }
00646 printf("(Min, Max) = (%.2f, %.2f)\n", m_TPLMin[index], m_TPLMax[index]);
00647 printf("\n");
00648 }
00649
00650 void CalcTPLMean(int bWidth, int bHeight)
00651 {
00652 for (int indexOfTPL=0;indexOfTPL<TPL_NUM;indexOfTPL++)
00653 {
00654 m_TPLMean[indexOfTPL] = 0;
00655 for (int i = 0; i < bWidth * bHeight; i ++)
00656 m_TPLMean[indexOfTPL] += m_Weight[indexOfTPL][i];
00657 }
00658
00659 if (m_verbose2)
00660 {
00661 printf("Template Mean Values TPL[0...2]: ");
00662 for (int indexOfTPL=0;indexOfTPL<TPL_NUM;indexOfTPL++)
00663 {
00664 printf("%.2f ",m_TPLMean[indexOfTPL]);
00665 }
00666 printf("\n\n");
00667 }
00668
00669 }
00670
00671 void OnShotStart(int bWidth, int bHeight)
00672 {
00673 if (!IsInShot)
00674 {
00675 for (int i = 0; i < bWidth * bHeight; i++)
00676 m_EnergyMap[i] = 1.0;
00677 memset(m_EnergyBuffer, 255, bWidth * bHeight);
00678
00679 IsInShot = TRUE;
00680 }
00681
00682
00683
00684 }
00685
00686 void OnShotEnd(int bWidth, int bHeight)
00687 {
00688 if (IsInShot)
00689 {
00690 IsInShot = FALSE;
00691 memset(m_EnergyBuffer, 0, bWidth * bHeight);
00692 }
00693
00694 }
00695
00696
00697
00698 void FillBuffer(int WindowLen, int bWidth, int bHeight, BYTE* mvseq)
00699 {
00700 double * Add = new double[bWidth * bHeight];
00701 if (IsInShot)
00702 {
00703 UINT BufferLen = bWidth * bHeight;
00704 double * Temp = new double[BufferLen];
00705 if (Temp == NULL || Add == NULL)
00706 {
00707 if (Temp != NULL) delete[] Temp;
00708 if (Add != NULL) delete[] Add;
00709 printf("Not Enough Memory! No Map Generated!");
00710 return;
00711 }
00712
00713
00714 for (int i = 0; i < BufferLen; i++)
00715 {
00716 m_EnergyMap[i] = 1.0;
00717 Add[i] = 0.0;
00718 }
00719
00720
00721
00722 for (int w = 0; w < WindowLen; w ++)
00723 {
00724 memset(Temp, 0, BufferLen * sizeof(double));
00725
00726
00727 memcpy(m_Buffer, mvseq + sizeof(BYTE)*bWidth*bHeight*2* w, BufferLen * 2);
00728
00729
00730 for (int i = 0; i < bWidth; i++)
00731 for (int j = 0; j < bHeight; j++)
00732 {
00733 double CurValue = m_EnergyMap[j * bWidth + i];
00734
00735 int cx, cy;
00736 long Ptr = 2 * (j * bWidth + i);
00737
00738
00739 cx = (char)m_Buffer[Ptr];
00740 cy = (char)m_Buffer[Ptr + 1];
00741
00742 char SignX, SignY;
00743 SignX = (cx >= 0)? 1:-1;
00744 SignY = (cy >= 0)? 1:-1;
00745
00746 int BaseX,BaseY;
00747 BaseX = i + (int)(cx / MVBLOCKSIZE);
00748 BaseY = j + (int)(cy / MVBLOCKSIZE);
00749
00750 double Factor;
00751 if (BaseX >= bWidth || BaseY >= bHeight || BaseX < 0 || BaseY < 0)
00752 {
00753 if (abs(cx) >= abs(cy))
00754 {
00755 Factor = (double)(cy) / (double)(cx);
00756 cx = ((SignX > 0)?bWidth:0) * MVBLOCKSIZE - MVBLOCKSIZE / 2;
00757 cy = Factor * cx + j * MVBLOCKSIZE - Factor * i * MVBLOCKSIZE;
00758 if (cy <= -MVBLOCKSIZE || cy >= bHeight * MVBLOCKSIZE)
00759 {
00760 cy = ((SignY > 0)?bHeight:0) * MVBLOCKSIZE - MVBLOCKSIZE / 2;
00761 cx = (cy - j * MVBLOCKSIZE + Factor * i * MVBLOCKSIZE) / Factor;
00762 }
00763 }
00764 else
00765 {
00766 Factor = (double)(cx) / (double)(cy);
00767 cy = ((SignY > 0)?bHeight:0) * MVBLOCKSIZE - MVBLOCKSIZE / 2;
00768 cx = Factor * cy + i * MVBLOCKSIZE - Factor * j * MVBLOCKSIZE;
00769 if (cx <= - MVBLOCKSIZE || cx >= bWidth * MVBLOCKSIZE)
00770 {
00771 cx = ((SignX > 0)?bWidth:0) * MVBLOCKSIZE - MVBLOCKSIZE / 2;
00772 cy = (cx - i * MVBLOCKSIZE + Factor * j * MVBLOCKSIZE) / Factor;
00773 }
00774 }
00775 cx -= i * MVBLOCKSIZE;
00776 cy -= j * MVBLOCKSIZE;
00777 BaseX = i + (int)(cx / MVBLOCKSIZE);
00778 BaseY = j + (int)(cy / MVBLOCKSIZE);
00779 }
00780
00781 double mX, mY;
00782 mX = (double)(abs(cx % MVBLOCKSIZE))/MVBLOCKSIZE;
00783 mY = (double)(abs(cy % MVBLOCKSIZE))/MVBLOCKSIZE;
00784 if (BaseX + SignX >= bWidth || BaseX + SignX < 0) mX = 0.0;
00785 if (BaseY + SignY >= bHeight || BaseY + SignY < 0) mY = 0.0;
00786
00787 Temp[BaseY * bWidth + BaseX] += (1 - mX) * (1 - mY) * CurValue;
00788
00789 if (BaseX + SignX < bWidth && BaseX + SignX >= 0)
00790 Temp[BaseY * bWidth + BaseX + SignX] += mX * (1 - mY) * CurValue;
00791 if (BaseY + SignY < bHeight && BaseY + SignY >= 0)
00792 {
00793 Temp[(BaseY + SignY) * bWidth + BaseX] += (1 - mX) * mY * CurValue;
00794 if (BaseX + SignX < bWidth && BaseX + SignX >= 0)
00795 Temp[(BaseY + SignY) * bWidth + BaseX + SignX] += mX * mY * CurValue;
00796 }
00797
00798 }
00799
00800 double * Exch;
00801 Exch = Temp;
00802 Temp = m_EnergyMap;
00803 m_EnergyMap = Exch;
00804
00805 for (int k = 0; k < bWidth * bHeight; k ++)
00806 Add[k] += m_EnergyMap[k];
00807
00808
00809
00810
00811
00812 }
00813 delete[] Temp;
00814
00815 }
00816
00817
00818 for (int i = 0; i < bWidth * bHeight; i ++)
00819 {
00820 m_EnergyMap[i] = Add[i] / WindowLen;
00821 m_EnergyBuffer[i] = (BYTE)(m_EnergyMap[i] * 255);
00822 }
00823 delete[] Add;
00824
00825
00826 if (m_verbose2)
00827 {
00828 DumpEnergyMap(bWidth, bHeight, "Average within Window (size=4)");
00829
00830 }
00831
00832 }
00833
00834
00835 double CalcEnergy(const int indexOfTPL, int bWidth, int bHeight, BOOL bNormalized=TRUE)
00836 {
00837 double Energy = 0;
00838 for (int i = 0; i < bWidth * bHeight; i ++)
00839 Energy += m_EnergyMap[i] * m_Weight[indexOfTPL][i];
00840
00841 if (bNormalized){
00842
00843 double min = m_TPLMin[indexOfTPL]*bWidth*bHeight;
00844 double max = m_TPLMax[indexOfTPL]*bWidth*bHeight;
00845 Energy = Normalization(Energy,min,max);
00846
00847 } else {
00848
00849
00850
00851
00852 Energy = Energy - m_TPLMean[indexOfTPL];
00853 }
00854 return Energy;
00855 }
00856
00857
00858 double Normalization(const double x, const double min, const double max)
00859 {
00860 return (x-min)/(max-min);
00861 }
00862
00863
00864
00865
00866 BOOL CalcMotionVectors(unsigned char* pre, unsigned char* cur, int Width, int Height, BYTE* mvseq, int index)
00867 {
00868
00869 int bWidth = Width / MVBLOCKSIZE;
00870 int bHeight = Height / MVBLOCKSIZE;
00871
00872 int i, j;
00873 int x, y, x_modify, y_modify;
00874 char sx, sy;
00875
00876 if (pre == NULL || cur == NULL)
00877 return TRUE;
00878
00879 int count=0;
00880 for (j = 0, y = 0; j < bHeight; j ++, y += 16)
00881 {
00882 for (i = 0, x = 0; i < bWidth; i ++, x += 16)
00883 {
00884 x_modify = x;
00885 y_modify = y;
00886 DiamondSearch16(pre, cur, Width, Height, &x_modify, &y_modify);
00887
00888
00889 sx = x_modify - x;
00890 sy = y_modify - y;
00891
00892 count += abs(sx)+abs(sy);
00893
00894
00895 mvseq[bWidth*bHeight*2*index + 2*(j*bWidth+i) + 0] = sx;
00896 mvseq[bWidth*bHeight*2*index + 2*(j*bWidth+i) + 1] = sy;
00897
00898 }
00899 }
00900
00901 return TRUE;
00902
00903 }
00904
00905
00906
00907
00908 int DiamondSearch16(unsigned char *refframe, unsigned char *desframe,
00909 int framewidth, int frameheight, int *cx, int *cy)
00910 {
00911 static char FirstDiamondX[] = { 0, 0, -2, 2, -1, 1, -1, 1};
00912 static char FirstDiamondY[] = {-2, 2, 0, 0, -1, -1, 1, 1};
00913 static char FinalDiamondX[] = {-1, 0, 1, 0};
00914 static char FinalDiamondY[] = { 0, -1, 0, 1};
00915
00916 static char CornerDiamondX[] = {0, 0, 1, 1, 2};
00917 static char CornerDiamondY[] = {2, -2, 1, -1, 0};
00918
00919 static char EdgeDiamondX[] = { 0, 1, 2};
00920 static char EdgeDiamondY[] = { 2, 1, 0};
00921
00922 int minX = 0, minY = 0, minerror;
00923 int curX, curY;
00924 int error, signX, signY;
00925 int sX, sY;
00926
00927 int i;
00928 unsigned char * block;
00929
00930
00931
00932 block = desframe + * cy * framewidth + * cx;
00933
00934 curX = * cx; curY = * cy;
00935 if (curX < 0 || curX > framewidth - 16 || curY < 0 || curY > frameheight - 16)
00936 {
00937 * cx = * cy = 0;
00938 return -1;
00939 }
00940
00941
00942 minerror = GetMotionError16(refframe, block, framewidth, curX, curY);
00943
00944 sX = * cx;
00945 sY = * cy;
00946 for (i = 0; i < 8; i ++)
00947 {
00948 curX = sX + FirstDiamondX[i];
00949 curY = sY + FirstDiamondY[i];
00950 if (curX < 0 || curX > framewidth - 16 || curY < 0 || curY > frameheight - 16)
00951 continue;
00952
00953 error = GetMotionError16(refframe, block, framewidth, curX, curY);
00954 if (error < minerror)
00955 {
00956 minX = FirstDiamondX[i];
00957 minY = FirstDiamondY[i];
00958 minerror = error;
00959 }
00960 }
00961
00962 while (1)
00963 {
00964 if (!minX && !minY) break;
00965
00966 sX += minX;
00967 sY += minY;
00968
00969 if (abs(sX - * cx) > MAX_DISP) break;
00970 if (abs(sY - * cy) > MAX_DISP) break;
00971
00972 if (!minY)
00973 {
00974 if (minX > 0) signX = 1;
00975 else signX = -1;
00976
00977 minX = minY = 0;
00978 for (i = 0; i < 5; i ++)
00979 {
00980 curX = sX + CornerDiamondX[i] * signX;
00981 curY = sY + CornerDiamondY[i];
00982 if (curX < 0 || curX > framewidth - 16 || curY < 0 || curY > frameheight - 16)
00983 continue;
00984
00985 error = GetMotionError16(refframe, block, framewidth, curX, curY);
00986 if (error < minerror)
00987 {
00988 minX = curX - sX;
00989 minY = curY - sY;
00990 minerror = error;
00991 }
00992 }
00993 continue;
00994 }
00995
00996 if (!minX)
00997 {
00998 if (minY > 0) signY = 1;
00999 else signY = -1;
01000
01001 minX = minY = 0;
01002 for (i = 0; i < 5; i ++)
01003 {
01004 curX = sX + CornerDiamondY[i];
01005 curY = sY + CornerDiamondX[i] * signY;
01006 if (curX < 0 || curX > framewidth - 16 || curY < 0 || curY > frameheight - 16)
01007 continue;
01008
01009 error = GetMotionError16(refframe, block, framewidth, curX, curY);
01010 if (error < minerror)
01011 {
01012 minX = curX - sX;
01013 minY = curY - sY;
01014 minerror = error;
01015 }
01016 }
01017 continue;
01018 }
01019
01020 if (minX > 0) signX = 1;
01021 else signX = -1;
01022 if (minY > 0) signY = 1;
01023 else signY = -1;
01024
01025 minX = minY = 0;
01026 for (i = 0; i < 3; i ++)
01027 {
01028 curX = sX + EdgeDiamondX[i] * signX;
01029 curY = sY + EdgeDiamondY[i] * signY;
01030 if (curX < 0 || curX > framewidth - 16 || curY < 0 || curY > frameheight - 16)
01031 continue;
01032
01033 error = GetMotionError16(refframe, block, framewidth, curX, curY);
01034 if (error < minerror)
01035 {
01036 minX = curX - sX;
01037 minY = curY - sY;
01038 minerror = error;
01039 }
01040 }
01041 }
01042
01043 for (i = 0; i < 4; i ++)
01044 {
01045 curX = sX + FinalDiamondX[i];
01046 curY = sY + FinalDiamondY[i];
01047 if (curX < 0 || curX > framewidth - 16 || curY < 0 || curY > frameheight - 16)
01048 continue;
01049
01050 error = GetMotionError16(refframe, block, framewidth, curX, curY);
01051 if (error < minerror)
01052 {
01053 minX = FinalDiamondX[i];
01054 minY = FinalDiamondY[i];
01055 minerror = error;
01056 }
01057 }
01058
01059 * cx = sX + minX;
01060 * cy = sY + minY;
01061 return minerror;
01062
01063 }
01064
01065 int FullSearch16(unsigned char *refframe, unsigned char *desframe, int framewidth, int frameheight, int *cx, int *cy)
01066 {
01067 int minerror;
01068 int curX, curY;
01069 int error, oX, oY;
01070 int sx, sy;
01071
01072 int i, j;
01073 unsigned char * block;
01074 block = desframe + * cy * framewidth + * cx;
01075
01076
01077 oX = curX = * cx;
01078 oY = curY = * cy;
01079 if (curX < 0 || curX > framewidth - 16|| curY < 0 || curY > frameheight - 16)
01080 {
01081 * cx = * cy = 0;
01082 return -1;
01083 }
01084 minerror = GetMotionError16(refframe, block, framewidth, curX, curY);
01085
01086 for (i = 1; i <= MAX_DISP; i ++)
01087 {
01088 sx = sy = -i;
01089 for (j = 0; j < 8 * i; j ++)
01090 {
01091 curX = oX + sx;
01092 curY = oY + sy;
01093
01094 if (!(curX < 0 || curX > framewidth - 16|| curY < 0 || curY > frameheight - 16))
01095 {
01096 error = GetMotionError16(refframe, block, framewidth, curX, curY);
01097 if (error < minerror)
01098 {
01099 minerror = error;
01100 * cx = curX;
01101 * cy = curY;
01102 }
01103 }
01104
01105 if (j < 2 * i) sx++;
01106 else if (j < 4 * i) sy++;
01107 else if (j < 6 * i) sx--;
01108 else sy--;
01109 }
01110 }
01111
01112 return minerror;
01113
01114 }
01115
01116
01117
01118
01119
01120
01121
01122
01123 int GetMotionError16(unsigned char * refframe, unsigned char * block,
01124 int framewidth, int fx, int fy)
01125 {
01126 int i,j;
01127 int SAD = 0;
01128 BYTE* refBlock = refframe + fy*framewidth + fx;
01129
01130
01131
01132 for (j=0;j<MVBLOCKSIZE;j++)
01133 for (i=0;i<MVBLOCKSIZE;i++)
01134 {
01135 int diff = block[j*framewidth+i] - refBlock[j*framewidth+i];
01136 diff = abs(diff);
01137 SAD+=diff;
01138 }
01139 return SAD;
01140 }
01141
01142
01143 protected:
01144
01145 int
01146 GetBinCount() const
01147 {
01148 return mBinCount;
01149 }
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189 template <class T>
01190 int
01191 ComputeBin(const T val, const T low, const T high, const int nrBins) const
01192 {
01193 const int bin = (nrBins * (val - low)) / (high - low);
01194 if (bin >= 0 && bin < nrBins)
01195 return bin;
01196
01197 if (val == high)
01198 return nrBins - 1;
01199
01200 ILOG_WARN("Unexpected value: " << val <<
01201 " is not in range [" << low << ", " << high << "]");
01202 return (bin < 0) ? 0 : nrBins-1;
01203 }
01204
01205 private:
01206
01207
01208
01209 Reporter* mReporter;
01210 String mFeatureName;
01211 int mBinCount;
01212 Feature::FeatureTable* mHistogramTable;
01213
01214
01215 double* m_Weight[TPL_NUM];
01216 double m_TPLMean[TPL_NUM];
01217 double m_TPLMin[TPL_NUM];
01218 double m_TPLMax[TPL_NUM];
01219 double* m_EnergyMap;
01220
01221 BOOL m_bNormalize;
01222
01223 BOOL IsInShot;
01224 BYTE* m_MVseq;
01225 BYTE* m_Buffer;
01226 BYTE* m_EnergyBuffer;
01227
01228 BOOL m_verbose;
01229 BOOL m_verbose2;
01230
01231 ILOG_VAR_DECL;
01232 };
01233
01234 ILOG_VAR_INIT(KfrMotionExtractor, Impala.Core.VideoSet);
01235
01236 }
01237 }
01238 }
01239
01240 #endif