Running Video with OpenCV on Modern Windows

clip_image002[4]Our latest contribution of open source code to the OpenCV project completes the relevant OpenCV libraries to enable  video modules to run on Modern Windows (Windows 8.1, Windows Phone 8.1, as well as the Windows 10 preview!).

Getting Started

To take advantage of this, you will first need to clone the OpenCv repo and follow the readme instructions to create the necessary set up to build a WinRT sample.

As is normal for many open source projects on GitHub, OpenCV ‘arrives’ in source form only. Therefore, in addition to the binaries, you will also need to generate the project files for Windows using CMake. Follow the steps outlined in the readme file.

Creating a Project

To begin, you will create a C++ project targeting Windows Store Apps (blank App)

image

Add an image control on the screen definition (MainPage.xaml) and give it a name (for this example, I have used “imgCV”)

clip_image006[4]

Add an implementation for the page loaded event. To do this, select the page property and double click on the Loaded event)

clip_image008[4]

At this point, you will now be ready to add the OpenCV code. Take note that you will need to reference the relevant libraries. You can certainly do that in the ‘classic’ C++ dialog box. But that process can become tedious and time-consuming if this is needed for all the platform and modes you plan to target (Win32, ARM, Debug/Release). If you are working with more than one, I encourage you to create and load a property page within the project.

Configuring the project to use OpenCV: Creating a Property Page

To do this, you will first need create the property page (there is a good example in the WinRT sample ). To load the property sheet, select the property sheet Manager:

clip_image010[4] 

Then form the property Manager, click on the + icon to add your property sheet

clip_image012[4]

(in this example I copy the one founded in the WinRT sample repo, who contains these lines:)

<None Include="$(OpenCV_Bin)opencv_videoio300$(DebugSuffix).dll">

      <DeploymentContent>true</DeploymentContent>

</None>

<AdditionalDependencies>opencv_core300$(DebugSuffix).lib;opencv_imgproc300$(DebugSuffix).lib;opencv_features2d300$(DebugSuffix).lib;opencv_flann300$(DebugSuffix).lib;opencv_ml300$(DebugSuffix).lib;opencv_imgcodecs300$(DebugSuffix).lib;opencv_objdetect300$(DebugSuffix).lib;opencv_videoio300$(DebugSuffix).lib;%(AdditionalDependencies)</AdditionalDependencies>

Configuring the project to use OpenCV: Creating the package

 

Now, you should be able to build. Yet, be sure that the Modern Windows package contain the necessary openCV dlls. You will need to select the dlls you want to be included in the package (for this sample you only need video support: opencv_core300, opencv_imgcdecs300, opencv_imgproc300 and opencv_video300)

Add each of these dlls from the binary folder you previously created using CMake and force the content property to true (it is possible to select all of the dlls and then apply the property for all of them at one time)

clip_image014[4]

In this sample, you can see that I added Release and Debug dlls to my sample project.

Adding the OpenCV code

To add code for the video:

First, declare the video capture:

                cv::VideoCapture cam;

Second, declare a global function to be used as VideoTask:

void cvVideoTask()

{

       cv::Mat frame;

       cam.open(0);

       while (1)

       {

              // get a new frame from camera - this is non-blocking per spec

              cam >> frame;

              if (!cam.grab()) continue;

              winrt_imshow();

       }

}

Third, within the Page Loaded event, add these two lines to identify the image control for displaying the video and the task function for video rendering:

void VideoCV::MainPage::Page_Loaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)

{

       cv::winrt_setFrameContainer(imgCV);

       cv::winrt_startMessageLoop(cvVideoTask);

}

 

You will now be ready to build and run (hit F5), and you should view this kind of result:

clip_image016[4]

(You can test this code from the sample located in the repo opencv\samples\winrt_universal\VideoCaptureXAML\video_capture_xaml)

Motion Detection, Just for Fun

A simplified approach to motion detection might be that if between two frames something had moved in the frame, the color of the pixels may have also changed. This algorithm will store the last frame and compare the current and prior frames pixel by pixel. In this example, any pixels that have changed will now appear in blue.

Declare a Compare function like this:

int seuil = 10;

void Compare(Mat f, Mat oldF)

{

        if (oldF.rows == 0)

                return;

 

 

 

        for (int i = 0; i < f.rows; i++)

        {

                for (int j = 0; j < f.cols; j++)

                {

                        if (abs(f.at<cv::Vec3b>(i, j)[2] - oldF.at<cv::Vec3b>(i, j)[2]) >seuil &&

                                abs(f.at<cv::Vec3b>(i, j)[0] - oldF.at<cv::Vec3b>(i, j)[0]) >seuil&&

                                abs(f.at<cv::Vec3b>(i, j)[1] - oldF.at<cv::Vec3b>(i, j)[1]) > seuil)

                        {

                                f.at<cv::Vec3b>(i, j)[2] = 255;

                                f.at<cv::Vec3b>(i, j)[1] = 0;

                                f.at<cv::Vec3b>(i, j)[0] = 0;

                        }

                }

        }

 

} 

Then call this function within your video task :

void cvVideoTask()

{

       cv::Mat frame,oldFrame,tmp;

       cam.open(0);

       while (1)

       {

              // get a new frame from camera - this is non-blocking per spec

              cam >> frame;

                     if (!cam.grab()) continue;

 

              frame.copyTo(tmp);

              Compare(frame, oldFrame);

              tmp.copyTo(oldFrame);

 

              winrt_imshow();

       }

}

 

You should have a similar result to this!

clip_image018[4]

Have fun with this demo, and don’t hesitate to share your feedback.

A bientôt !