Saturday, 5 July 2014

PhotoStitcher Demo



Add ability to choose photos to stitch, directly from dialog (GUI)




=============FileDialog.cpp================

#include <new>
#include <shlobj.h>
#include <shlwapi.h>


#include <vector>
#include <string>
#include <iostream>



using namespace std;


const COMDLG_FILTERSPEC c_rgFileTypes[] =
{
 { L"Images", L"*.jpg;*.jpeg" },
 { L"All Files (*.*)", L"*.*" }
};


void MultiselectInvoke(vector<string> *ret)
{
 ret->clear();
 // CHM - Initialise for COM objects
 

 IFileOpenDialog *pfd = NULL;

 // CoCreate the dialog object.
 HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog,
  NULL,
  CLSCTX_INPROC_SERVER,
  IID_PPV_ARGS(&pfd));

 if (SUCCEEDED(hr))
 {
  DWORD dwOptions;
  // Specify multiselect.
  hr = pfd->GetOptions(&dwOptions);
  if (SUCCEEDED(hr))
  {
   hr = pfd->SetOptions(dwOptions | FOS_ALLOWMULTISELECT);
  }

  // Set the file types to display only. 
  // Notice that this is a 1-based array.
  pfd->SetFileTypes(ARRAYSIZE(c_rgFileTypes), c_rgFileTypes);
  pfd->SetTitle(L"[CHM] Select of Images to Stitch");

  if (SUCCEEDED(hr))
  {
   // Show the Open dialog.
   hr = pfd->Show(GetFocus());

   if (SUCCEEDED(hr))
   {
    // Obtain the result of the user interaction.
    IShellItemArray *psiaResults;
    hr = pfd->GetResults(&psiaResults);

    if (SUCCEEDED(hr))
    {
     DWORD dwFolderCount;
     hr = psiaResults->GetCount(&dwFolderCount);
     if (SUCCEEDED(hr))
     {

      for (DWORD i = 0; i < dwFolderCount; i++)
      {
       IShellItem *psi = NULL;
       if (SUCCEEDED(psiaResults->GetItemAt(i, &psi)))
       {
        // Retrieve the file path.
        // CHM - It is ok not to initialise, as the pointer \
        is assigned in the following function
        LPWSTR pszPath = NULL;
        if (SUCCEEDED(psi->GetDisplayName(SIGDN_FILESYSPATH,&pszPath)))
        {

         // Geting short version of path, elimating some problem (not all) \
         of unicode path
         DWORD wlen = GetShortPathName(pszPath, NULL, 0);
         LPWSTR s_pszPath = new wchar_t[wlen];
         GetShortPathName(pszPath, s_pszPath, wlen);


         int size_needed = WideCharToMultiByte(CP_ACP, NULL, s_pszPath, -1, NULL, NULL, NULL, NULL);
         LPSTR pszPathA = (char *)CoTaskMemAlloc(size_needed);
         WideCharToMultiByte(CP_ACP, NULL, s_pszPath, -1, pszPathA, size_needed, NULL, NULL);

         delete[]  s_pszPath;

         ret->push_back(pszPathA);

         CoTaskMemFree(pszPathA);
         CoTaskMemFree(pszPath);
        }
        psi->Release();
       }
      }

     }
     psiaResults->Release();
    }
   }
  }
  pfd->Release();
 }
 
 
 return;
}

=============================================



===============main.cpp=========================
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <opencv\cv.h>
#include <opencv2\stitching\stitcher.hpp>

#include <windows.h>
#include "FileDialog.h"


using namespace cv;
using namespace std;



int main(int argc, char** argv)
{
 SetConsoleTitle(L"[CHM] Photo-Stitcher Demo");
 cout << "Powered by OpenCV (2.4.9) libraries" << endl;
 cout << "Coded in Visual C++ 2013"<<endl;

#if _WIN64 
 cout << "x64"<<endl;
#else
 cout << "x86"<<endl;
#endif

#if _DEBUG
 cout << "Debug build"<<endl;
#else
 cout << "Release build"<<endl;
#endif

 cout << endl<< "====Program Start====" << endl << "Opening Photos...";

 vector<string> imgpaths;

 CoInitialize(NULL);
 MultiselectInvoke(&imgpaths);
 while (imgpaths.size()<2)
 {
  
  int hr = MessageBox(GetFocus(),
   L"Two or more photos are required!",
   L"[CHM] Photo-Stitcher",
   MB_RETRYCANCEL | MB_ICONINFORMATION);

  if (hr == IDCANCEL)
   return 0;
  else if (hr == IDRETRY);

  MultiselectInvoke(&imgpaths);
 }
 CoUninitialize();
 cout << " -Done" << endl;

 vector< Mat > vImg;
 Mat rImg;

 Mat image;
 image = imread(imgpaths[0], IMREAD_COLOR); // Read the file

 if (!image.data) // Check for invalid input
 {
  cout << "Could not open or find the image" << std::endl;
  return -1;
 }

 cout << "Blurring Function Test";
 GaussianBlur( image, image, Size( 31, 31 ), 0, 0 );

 namedWindow("[CHM] Display 1st pic", CV_WINDOW_NORMAL | CV_WINDOW_KEEPRATIO);
 resizeWindow("[CHM] Display 1st pic", image.cols*0.1, image.rows*0.1);
 imshow("[CHM] Display 1st pic", image);
 
 cout << " -Done" << endl;
 

 waitKey(0); // Wait for a keystroke in the window
 destroyAllWindows();



 cout <<endl<< "Stitching Test" << endl;
 cout << "> Loading Photos... ";
 DWORD i, n;
 n = imgpaths.size();
 for (i = 0; i < n; i++)
 {
  vImg.push_back(imread(imgpaths[i]));
 }
  

 cout << " -Done" << endl;

 cout << "> Resolution is " << vImg.at(0).cols<<"W" << " * " << vImg.at(0).rows <<"H, for Each Photo" <<endl;
 Stitcher stitcher = Stitcher::createDefault();


 unsigned long AAtime = 0, BBtime = 0; //check processing time  
 AAtime = getTickCount(); //check processing time  

 stitcher.stitch(vImg, rImg);

 BBtime = getTickCount(); //check processing time   

 cout << "Done,";
 printf("%.2lf sec \n", (BBtime - AAtime) / getTickFrequency()); //check processing time  


 namedWindow("[CHM]Stitching Result", CV_WINDOW_NORMAL | CV_WINDOW_KEEPRATIO);
 resizeWindow("[CHM]Stitching Result", rImg.cols*0.19, rImg.rows*0.19);

 imshow("[CHM]Stitching Result", rImg);

#ifndef _DEBUG
 SYSTEMTIME systime;
 GetLocalTime(&systime);

 stringstream outpath;
 outpath << "PanoramaCV_" << setfill('0') << setw(2) << systime.wMonth 
  << "_" << setfill('0') << setw(2) << systime.wDay << ".jpg";

 imwrite(outpath.str(), rImg);

 waitKey(0); // Wait for a keystroke in the window
#endif

 cout << "====End of Program====" << endl;
 return 0;
}

=======================================================