mirror of
https://github.com/opencv/opencv.git
synced 2024-12-04 00:39:11 +08:00
VideoCapture with digital camera and gPhoto2 library
This commit is contained in:
parent
298c98ea32
commit
6d0407b65e
@ -205,6 +205,7 @@ OCV_OPTION(WITH_DIRECTX "Include DirectX support" ON
|
||||
OCV_OPTION(WITH_INTELPERC "Include Intel Perceptual Computing support" OFF IF (WIN32 AND NOT WINRT) )
|
||||
OCV_OPTION(WITH_IPP_A "Include Intel IPP_A support" OFF IF (MSVC OR X86 OR X86_64) )
|
||||
OCV_OPTION(WITH_GDAL "Include GDAL Support" OFF IF (NOT ANDROID AND NOT IOS AND NOT WINRT) )
|
||||
OCV_OPTION(WITH_GPHOTO2 "Include gPhoto2 library support" ON IF (UNIX AND NOT ANDROID) )
|
||||
|
||||
# OpenCV build components
|
||||
# ===================================================
|
||||
@ -1032,6 +1033,10 @@ if(DEFINED WITH_INTELPERC)
|
||||
status(" Intel PerC:" HAVE_INTELPERC THEN "YES" ELSE NO)
|
||||
endif(DEFINED WITH_INTELPERC)
|
||||
|
||||
if(DEFINED WITH_GPHOTO2)
|
||||
status(" gPhoto2:" HAVE_GPHOTO2 THEN "YES" ELSE NO)
|
||||
endif(DEFINED WITH_GPHOTO2)
|
||||
|
||||
|
||||
# ========================== Other third-party libraries ==========================
|
||||
status("")
|
||||
|
@ -311,3 +311,9 @@ endif()
|
||||
if(WITH_INTELPERC)
|
||||
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVFindIntelPerCSDK.cmake")
|
||||
endif(WITH_INTELPERC)
|
||||
|
||||
# --- gPhoto2 ---
|
||||
ocv_clear_vars(HAVE_GPHOTO2)
|
||||
if(WITH_GPHOTO2)
|
||||
CHECK_MODULE(libgphoto2 HAVE_GPHOTO2)
|
||||
endif(WITH_GPHOTO2)
|
||||
|
@ -178,3 +178,6 @@
|
||||
/* Define if your processor stores words with the most significant byte
|
||||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
#cmakedefine WORDS_BIGENDIAN
|
||||
|
||||
/* gPhoto2 library */
|
||||
#cmakedefine HAVE_GPHOTO2
|
||||
|
@ -186,6 +186,10 @@ if(HAVE_INTELPERC)
|
||||
list(APPEND VIDEOIO_LIBRARIES ${INTELPERC_LIBRARIES})
|
||||
endif(HAVE_INTELPERC)
|
||||
|
||||
if(HAVE_GPHOTO2)
|
||||
list(APPEND videoio_srcs ${CMAKE_CURRENT_LIST_DIR}/src/cap_gphoto2.cpp)
|
||||
endif(HAVE_GPHOTO2)
|
||||
|
||||
if(IOS)
|
||||
add_definitions(-DHAVE_IOS=1)
|
||||
list(APPEND videoio_srcs
|
||||
|
@ -89,7 +89,8 @@ enum { CAP_ANY = 0, // autodetect
|
||||
CAP_WINRT = 1410, // Microsoft Windows Runtime using Media Foundation
|
||||
CAP_INTELPERC = 1500, // Intel Perceptual Computing SDK
|
||||
CAP_OPENNI2 = 1600, // OpenNI2 (for Kinect)
|
||||
CAP_OPENNI2_ASUS = 1610 // OpenNI2 (for Asus Xtion and Occipital Structure sensors)
|
||||
CAP_OPENNI2_ASUS = 1610, // OpenNI2 (for Asus Xtion and Occipital Structure sensors)
|
||||
CAP_GPHOTO2 = 1700 // gPhoto2 connection
|
||||
};
|
||||
|
||||
// generic properties (based on DC1394 properties)
|
||||
@ -382,6 +383,23 @@ enum { VIDEOWRITER_PROP_QUALITY = 1, // Quality (0..100%) of the videostream
|
||||
VIDEOWRITER_PROP_FRAMEBYTES = 2, // (Read-only): Size of just encoded video frame
|
||||
};
|
||||
|
||||
// gPhoto2 properties, if propertyId is less than 0 then work on widget with that __additive inversed__ camera setting ID
|
||||
// Get IDs by using CAP_PROP_GPHOTO2_WIDGET_ENUMERATE.
|
||||
// @see CvCaptureCAM_GPHOTO2 for more info
|
||||
enum { CAP_PROP_GPHOTO2_PREVIEW = 17001, // Capture only preview from liveview mode.
|
||||
CAP_PROP_GPHOTO2_WIDGET_ENUMERATE = 17002, // Readonly, returns (const char *).
|
||||
CAP_PROP_GPHOTO2_RELOAD_CONFIG = 17003, // Trigger, only by set. Reload camera settings.
|
||||
CAP_PROP_GPHOTO2_RELOAD_ON_CHANGE = 17004, // Reload all settings on set.
|
||||
CAP_PROP_GPHOTO2_COLLECT_MSGS = 17005, // Collect messages with details.
|
||||
CAP_PROP_GPHOTO2_FLUSH_MSGS = 17006, // Readonly, returns (const char *).
|
||||
CAP_PROP_SPEED = 17007, // Exposure speed. Can be readonly, depends on camera program.
|
||||
CAP_PROP_APERTURE = 17008, // Aperture. Can be readonly, depends on camera program.
|
||||
CAP_PROP_EXPOSUREPROGRAM = 17009, // Camera exposure program.
|
||||
CAP_PROP_VIEWFINDER = 17010 // Enter liveview mode.
|
||||
};
|
||||
|
||||
//enum {
|
||||
|
||||
class IVideoCapture;
|
||||
|
||||
/** @brief Class for video capturing from video files, image sequences or cameras. The class provides C++ API
|
||||
|
@ -110,7 +110,9 @@ enum
|
||||
|
||||
CV_CAP_INTELPERC = 1500, // Intel Perceptual Computing
|
||||
|
||||
CV_CAP_OPENNI2 = 1600 // OpenNI2 (for Kinect)
|
||||
CV_CAP_OPENNI2 = 1600, // OpenNI2 (for Kinect)
|
||||
|
||||
CV_CAP_GPHOTO2 = 1700
|
||||
};
|
||||
|
||||
/* start capturing frames from camera: index = camera_index + domain_offset (CV_CAP_*) */
|
||||
@ -391,6 +393,23 @@ enum
|
||||
CV_CAP_INTELPERC_IMAGE = 3
|
||||
};
|
||||
|
||||
// gPhoto2 properties, if propertyId is less than 0 then work on widget with that __additive inversed__ camera setting ID
|
||||
// Get IDs by using CAP_PROP_GPHOTO2_WIDGET_ENUMERATE.
|
||||
// @see CvCaptureCAM_GPHOTO2 for more info
|
||||
enum
|
||||
{
|
||||
CV_CAP_PROP_GPHOTO2_PREVIEW = 17001, // Capture only preview from liveview mode.
|
||||
CV_CAP_PROP_GPHOTO2_WIDGET_ENUMERATE = 17002, // Readonly, returns (const char *).
|
||||
CV_CAP_PROP_GPHOTO2_RELOAD_CONFIG = 17003, // Trigger, only by set. Reload camera settings.
|
||||
CV_CAP_PROP_GPHOTO2_RELOAD_ON_CHANGE = 17004, // Reload all settings on set.
|
||||
CV_CAP_PROP_GPHOTO2_COLLECT_MSGS = 17005, // Collect messages with details.
|
||||
CV_CAP_PROP_GPHOTO2_FLUSH_MSGS = 17006, // Readonly, returns (const char *).
|
||||
CV_CAP_PROP_SPEED = 17007, // Exposure speed. Can be readonly, depends on camera program.
|
||||
CV_CAP_PROP_APERTURE = 17008, // Aperture. Can be readonly, depends on camera program.
|
||||
CV_CAP_PROP_EXPOSUREPROGRAM = 17009, // Camera exposure program.
|
||||
CV_CAP_PROP_VIEWFINDER = 17010 // Enter liveview mode.
|
||||
};
|
||||
|
||||
/* retrieve or set capture properties */
|
||||
CVAPI(double) cvGetCaptureProperty( CvCapture* capture, int property_id );
|
||||
CVAPI(int) cvSetCaptureProperty( CvCapture* capture, int property_id, double value );
|
||||
|
@ -518,6 +518,9 @@ static Ptr<IVideoCapture> IVideoCapture_create(int index)
|
||||
#endif
|
||||
#ifdef WINRT_VIDEO
|
||||
CAP_WINRT,
|
||||
#endif
|
||||
#ifdef HAVE_GPHOTO2
|
||||
CV_CAP_GPHOTO2,
|
||||
#endif
|
||||
-1, -1
|
||||
};
|
||||
@ -537,6 +540,7 @@ static Ptr<IVideoCapture> IVideoCapture_create(int index)
|
||||
#if defined(HAVE_DSHOW) || \
|
||||
defined(HAVE_INTELPERC) || \
|
||||
defined(WINRT_VIDEO) || \
|
||||
defined(HAVE_GPHOTO2) || \
|
||||
(0)
|
||||
Ptr<IVideoCapture> capture;
|
||||
|
||||
@ -558,6 +562,11 @@ static Ptr<IVideoCapture> IVideoCapture_create(int index)
|
||||
if (capture)
|
||||
return capture;
|
||||
break; // CAP_WINRT
|
||||
#endif
|
||||
#ifdef HAVE_GPHOTO2
|
||||
case CV_CAP_GPHOTO2:
|
||||
capture = createGPhoto2Capture(index);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
if (capture && capture->isOpened())
|
||||
@ -571,15 +580,38 @@ static Ptr<IVideoCapture> IVideoCapture_create(int index)
|
||||
|
||||
|
||||
static Ptr<IVideoCapture> IVideoCapture_create(const String& filename)
|
||||
{
|
||||
int domains[] =
|
||||
{
|
||||
CV_CAP_ANY,
|
||||
#ifdef HAVE_GPHOTO2
|
||||
CV_CAP_GPHOTO2,
|
||||
#endif
|
||||
-1, -1
|
||||
};
|
||||
|
||||
// try every possibly installed camera API
|
||||
for (int i = 0; domains[i] >= 0; i++)
|
||||
{
|
||||
Ptr<IVideoCapture> capture;
|
||||
|
||||
switch (domains[i])
|
||||
{
|
||||
case CV_CAP_ANY:
|
||||
capture = createMotionJpegCapture(filename);
|
||||
break;
|
||||
#ifdef HAVE_GPHOTO2
|
||||
case CV_CAP_GPHOTO2:
|
||||
capture = createGPhoto2Capture(filename);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (capture && capture->isOpened())
|
||||
{
|
||||
return capture;
|
||||
}
|
||||
|
||||
}
|
||||
// failed open a camera
|
||||
return Ptr<IVideoCapture>();
|
||||
}
|
||||
|
1227
modules/videoio/src/cap_gphoto2.cpp
Normal file
1227
modules/videoio/src/cap_gphoto2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -186,6 +186,9 @@ namespace cv
|
||||
|
||||
Ptr<IVideoCapture> createMotionJpegCapture(const String& filename);
|
||||
Ptr<IVideoWriter> createMotionJpegWriter( const String& filename, double fps, Size frameSize, bool iscolor );
|
||||
|
||||
Ptr<IVideoCapture> createGPhoto2Capture(int index);
|
||||
Ptr<IVideoCapture> createGPhoto2Capture(const String& deviceName);
|
||||
};
|
||||
|
||||
#endif /* __VIDEOIO_H_ */
|
||||
|
@ -37,6 +37,7 @@
|
||||
defined(HAVE_AVFOUNDATION) || \
|
||||
defined(HAVE_GIGE_API) || \
|
||||
defined(HAVE_INTELPERC) || \
|
||||
defined(HAVE_GPHOTO2) || \
|
||||
(0)
|
||||
//defined(HAVE_ANDROID_NATIVE_CAMERA) || - enable after #1193
|
||||
# define BUILD_WITH_CAMERA_SUPPORT 1
|
||||
|
460
samples/cpp/autofocus.cpp
Normal file
460
samples/cpp/autofocus.cpp
Normal file
@ -0,0 +1,460 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Piotr Dobrowolski dobrypd[at]gmail[dot]com
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
const char * windowOriginal = "Captured preview";
|
||||
const int FOCUS_STEP = 1024;
|
||||
const int MAX_FOCUS_STEP = 32767;
|
||||
const int FOCUS_DIRECTION_INFTY = 1;
|
||||
const int DEFAULT_BREAK_LIMIT = 5;
|
||||
const int DEFAULT_OUTPUT_FPS = 20;
|
||||
const double epsylon = 0.0005; // compression, noice, etc.
|
||||
|
||||
struct Args_t
|
||||
{
|
||||
const char * deviceName;
|
||||
const char * output;
|
||||
unsigned int fps;
|
||||
unsigned int minimumFocusStep;
|
||||
unsigned int breakLimit;
|
||||
bool measure;
|
||||
bool verbose;
|
||||
} GlobalArgs;
|
||||
|
||||
struct FocusState
|
||||
{
|
||||
int step;
|
||||
int direction;
|
||||
int minFocusStep;
|
||||
int lastDirectionChange;
|
||||
int stepToLastMax;
|
||||
double rate;
|
||||
double rateMax;
|
||||
};
|
||||
|
||||
static ostream & operator<<(ostream & os, FocusState & state)
|
||||
{
|
||||
return os << "RATE=" << state.rate << "\tSTEP="
|
||||
<< state.step * state.direction << "\tLast change="
|
||||
<< state.lastDirectionChange << "\tstepToLastMax="
|
||||
<< state.stepToLastMax;
|
||||
}
|
||||
|
||||
static FocusState createInitialState()
|
||||
{
|
||||
FocusState state;
|
||||
state.step = FOCUS_STEP;
|
||||
state.direction = FOCUS_DIRECTION_INFTY;
|
||||
state.minFocusStep = 0;
|
||||
state.lastDirectionChange = 0;
|
||||
state.stepToLastMax = 0;
|
||||
state.rate = 0;
|
||||
state.rateMax = 0;
|
||||
return state;
|
||||
}
|
||||
|
||||
static void focusDriveEnd(VideoCapture & cap, int direction)
|
||||
{
|
||||
while (cap.set(CAP_PROP_ZOOM, (double) MAX_FOCUS_STEP * direction))
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimal focus step depends on lens
|
||||
* and I don't want to make any assumptions about it.
|
||||
*/
|
||||
static int findMinFocusStep(VideoCapture & cap, unsigned int startWith,
|
||||
int direction)
|
||||
{
|
||||
int lStep, rStep;
|
||||
lStep = 0;
|
||||
rStep = startWith;
|
||||
|
||||
focusDriveEnd(cap, direction * FOCUS_DIRECTION_INFTY);
|
||||
while (lStep < rStep)
|
||||
{
|
||||
int mStep = (lStep + rStep) / 2;
|
||||
cap.set(CAP_PROP_ZOOM, direction * FOCUS_DIRECTION_INFTY * FOCUS_STEP);
|
||||
if (cap.set(CAP_PROP_ZOOM, -direction * mStep))
|
||||
{
|
||||
rStep = mStep;
|
||||
}
|
||||
else
|
||||
{
|
||||
lStep = mStep + 1;
|
||||
}
|
||||
}
|
||||
cap.set(CAP_PROP_ZOOM, direction * FOCUS_DIRECTION_INFTY * MAX_FOCUS_STEP);
|
||||
if (GlobalArgs.verbose)
|
||||
{
|
||||
cout << "Found minimal focus step = " << lStep << endl;
|
||||
}
|
||||
return lStep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rate frame from 0/blury/ to 1/sharp/.
|
||||
*/
|
||||
static double rateFrame(Mat & frame)
|
||||
{
|
||||
unsigned long int sum = 0;
|
||||
unsigned long int size = frame.cols * frame.rows;
|
||||
Mat edges;
|
||||
cvtColor(frame, edges, CV_BGR2GRAY);
|
||||
GaussianBlur(edges, edges, Size(7, 7), 1.5, 1.5);
|
||||
Canny(edges, edges, 0, 30, 3);
|
||||
|
||||
MatIterator_<uchar> it, end;
|
||||
for (it = edges.begin<uchar>(), end = edges.end<uchar>(); it != end; ++it)
|
||||
{
|
||||
sum += *it != 0;
|
||||
}
|
||||
|
||||
return (double) sum / (double) size;
|
||||
}
|
||||
|
||||
static int correctFocus(bool lastSucceeded, FocusState & state, double rate)
|
||||
{
|
||||
if (GlobalArgs.verbose)
|
||||
{
|
||||
cout << "RATE=" << rate << endl;
|
||||
}
|
||||
state.lastDirectionChange++;
|
||||
double rateDelta = rate - state.rate;
|
||||
|
||||
if (rate >= state.rateMax + epsylon)
|
||||
{
|
||||
// Update Max
|
||||
state.stepToLastMax = 0;
|
||||
state.rateMax = rate;
|
||||
// My local minimum is now on the other direction, that's why:
|
||||
state.lastDirectionChange = 0;
|
||||
}
|
||||
|
||||
if (!lastSucceeded)
|
||||
{
|
||||
// Focus at limit or other problem, change the direction.
|
||||
state.direction *= -1;
|
||||
state.lastDirectionChange = 0;
|
||||
state.step /= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rate < epsylon)
|
||||
{ // It's hard to say anything
|
||||
state.step = FOCUS_STEP;
|
||||
}
|
||||
else if (rateDelta < -epsylon)
|
||||
{ // Wrong direction ?
|
||||
state.direction *= -1;
|
||||
state.step = static_cast<int>(static_cast<double>(state.step) * 0.75);
|
||||
state.lastDirectionChange = 0;
|
||||
}
|
||||
else if ((rate + epsylon < state.rateMax)
|
||||
&& ((state.lastDirectionChange > 3)
|
||||
|| ((state.step < (state.minFocusStep * 1.5))
|
||||
&& state.stepToLastMax > state.step)))
|
||||
{ // I've done 3 steps (or I'm finishing) without improvement, go back to max.
|
||||
state.direction = state.stepToLastMax >= 0 ? 1 : -1;
|
||||
state.step = static_cast<int>(static_cast<double>(state.step) * 0.75);
|
||||
int stepToMax = abs(state.stepToLastMax);
|
||||
state.stepToLastMax = 0;
|
||||
state.lastDirectionChange = 0; // Like reset.
|
||||
state.rate = rate;
|
||||
return stepToMax;
|
||||
}
|
||||
}
|
||||
// Update state.
|
||||
state.rate = rate;
|
||||
state.stepToLastMax -= state.direction * state.step;
|
||||
return state.step;
|
||||
}
|
||||
|
||||
static void showHelp(const char * pName, bool welcomeMsg)
|
||||
{
|
||||
cout << "This program demonstrates usage of gPhoto2 VideoCapture.\n\n"
|
||||
"With OpenCV build without gPhoto2 library support it will "
|
||||
"do nothing special, just capture.\n\n"
|
||||
"Simple implementation of autofocus is based on edges detection.\n"
|
||||
"It was tested (this example) only with Nikon DSLR (Nikon D90).\n"
|
||||
"But shall work on all Nikon DSLRs, and with little effort with other devices.\n"
|
||||
"Visit http://www.gphoto.org/proj/libgphoto2/support.php\n"
|
||||
"to find supported devices (need Image Capture at least).\n"
|
||||
"Before run, set your camera autofocus ON.\n\n";
|
||||
|
||||
if (!welcomeMsg)
|
||||
{
|
||||
cout << "usage " << pName << ": [OPTIONS] DEVICE_NAME\n\n"
|
||||
"OPTIONS:\n"
|
||||
"\t-h\t\treturns this help message,\n"
|
||||
"\t-o FILENAME\tsave output video in file (MJPEG only),\n"
|
||||
"\t-f FPS\t\tframes per second in output video,\n"
|
||||
"\t-m\t\tmeasure exposition\n"
|
||||
"\t\t\t(returns rates from closest focus to INTY\n"
|
||||
"\t\t\tfor every minimum step),\n"
|
||||
"\t-d INT\t\tset minimum focus step,\n"
|
||||
"\t-v\t\tverbose mode.\n\n\n"
|
||||
"DEVICE_NAME\t\tis your digital camera model substring.\n\n\n"
|
||||
"On runtime you can use keys to control:\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Actions:\n";
|
||||
}
|
||||
|
||||
cout << "\tk:\t- focus out,\n"
|
||||
"\tj:\t- focus in,\n"
|
||||
"\t,:\t- focus to the closest point,\n"
|
||||
"\t.:\t- focus to infinity,\n"
|
||||
"\tr:\t- reset autofocus state,\n"
|
||||
"\tf:\t- switch autofocus on/off,\n"
|
||||
"\tq:\t- quit.\n";
|
||||
}
|
||||
|
||||
static bool parseArguments(int argc, char ** argv)
|
||||
{
|
||||
int index;
|
||||
GlobalArgs.deviceName = "Nikon";
|
||||
GlobalArgs.output = NULL;
|
||||
GlobalArgs.fps = DEFAULT_OUTPUT_FPS;
|
||||
GlobalArgs.minimumFocusStep = 0;
|
||||
GlobalArgs.breakLimit = DEFAULT_BREAK_LIMIT;
|
||||
GlobalArgs.measure = false;
|
||||
GlobalArgs.verbose = false;
|
||||
|
||||
for (index = 1; index < argc; index++)
|
||||
{
|
||||
const char * arg = argv[index];
|
||||
if (strcmp(arg, "-h") == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (strcmp(arg, "-o") == 0)
|
||||
{
|
||||
GlobalArgs.output = argv[++index];
|
||||
}
|
||||
else if (strcmp(arg, "-f") == 0)
|
||||
{
|
||||
if (sscanf(argv[++index], "%u", &GlobalArgs.fps) != 1
|
||||
|| GlobalArgs.fps <= 0)
|
||||
{
|
||||
cerr << "Invalid fps argument." << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (strcmp(arg, "-m") == 0)
|
||||
{
|
||||
GlobalArgs.measure = true;
|
||||
}
|
||||
else if (strcmp(arg, "-v") == 0)
|
||||
{
|
||||
GlobalArgs.verbose = true;
|
||||
}
|
||||
else if (strcmp(arg, "-d") == 0)
|
||||
{
|
||||
if (sscanf(argv[++index], "%u", &GlobalArgs.minimumFocusStep) != 1
|
||||
|| GlobalArgs.minimumFocusStep <= 0)
|
||||
{
|
||||
cerr << "Invalid minimum focus step argument." << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (arg[0] != '-')
|
||||
{
|
||||
GlobalArgs.deviceName = arg;
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "Unknown option " << arg << endl;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
if (!parseArguments(argc, argv))
|
||||
{
|
||||
showHelp(argv[0], false);
|
||||
return -1;
|
||||
}
|
||||
VideoCapture cap(GlobalArgs.deviceName);
|
||||
if (!cap.isOpened())
|
||||
{
|
||||
cout << "Cannot find device " << GlobalArgs.deviceName << endl;
|
||||
showHelp(argv[0], false);
|
||||
return -1;
|
||||
}
|
||||
|
||||
VideoWriter videoWriter;
|
||||
Mat frame;
|
||||
FocusState state = createInitialState();
|
||||
bool focus = true;
|
||||
bool lastSucceeded = true;
|
||||
namedWindow(windowOriginal, 1);
|
||||
|
||||
// Get settings:
|
||||
if (GlobalArgs.verbose)
|
||||
{
|
||||
if ((cap.get(CAP_PROP_GPHOTO2_WIDGET_ENUMERATE) == 0)
|
||||
|| (cap.get(CAP_PROP_GPHOTO2_WIDGET_ENUMERATE) == -1))
|
||||
{
|
||||
// Some VideoCapture implementations can return -1, 0.
|
||||
cout << "This is not GPHOTO2 device." << endl;
|
||||
return -2;
|
||||
}
|
||||
cout << "List of camera settings: " << endl
|
||||
<< (const char *) (intptr_t) cap.get(CAP_PROP_GPHOTO2_WIDGET_ENUMERATE)
|
||||
<< endl;
|
||||
cap.set(CAP_PROP_GPHOTO2_COLLECT_MSGS, true);
|
||||
}
|
||||
|
||||
cap.set(CAP_PROP_GPHOTO2_PREVIEW, true);
|
||||
cap.set(CAP_PROP_VIEWFINDER, true);
|
||||
cap >> frame; // To check PREVIEW output Size.
|
||||
if (GlobalArgs.output != NULL)
|
||||
{
|
||||
Size S = Size((int) cap.get(CAP_PROP_FRAME_WIDTH), (int) cap.get(CAP_PROP_FRAME_HEIGHT));
|
||||
int fourCC = CV_FOURCC('M', 'J', 'P', 'G');
|
||||
videoWriter.open(GlobalArgs.output, fourCC, GlobalArgs.fps, S, true);
|
||||
if (!videoWriter.isOpened())
|
||||
{
|
||||
cerr << "Cannot open output file " << GlobalArgs.output << endl;
|
||||
showHelp(argv[0], false);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
showHelp(argv[0], true); // welcome msg
|
||||
|
||||
if (GlobalArgs.minimumFocusStep == 0)
|
||||
{
|
||||
state.minFocusStep = findMinFocusStep(cap, FOCUS_STEP / 16, -FOCUS_DIRECTION_INFTY);
|
||||
}
|
||||
else
|
||||
{
|
||||
state.minFocusStep = GlobalArgs.minimumFocusStep;
|
||||
}
|
||||
focusDriveEnd(cap, -FOCUS_DIRECTION_INFTY); // Start with closest
|
||||
|
||||
char key = 0;
|
||||
while (key != 'q' && key != 27 /*ESC*/)
|
||||
{
|
||||
cap >> frame;
|
||||
if (frame.empty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (GlobalArgs.output != NULL)
|
||||
{
|
||||
videoWriter << frame;
|
||||
}
|
||||
|
||||
if (focus && !GlobalArgs.measure)
|
||||
{
|
||||
int stepToCorrect = correctFocus(lastSucceeded, state, rateFrame(frame));
|
||||
lastSucceeded = cap.set(CAP_PROP_ZOOM,
|
||||
max(stepToCorrect, state.minFocusStep) * state.direction);
|
||||
if ((!lastSucceeded) || (stepToCorrect < state.minFocusStep))
|
||||
{
|
||||
if (--GlobalArgs.breakLimit <= 0)
|
||||
{
|
||||
focus = false;
|
||||
state.step = state.minFocusStep * 4;
|
||||
cout << "In focus, you can press 'f' to improve with small step, "
|
||||
"or 'r' to reset." << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GlobalArgs.breakLimit = DEFAULT_BREAK_LIMIT;
|
||||
}
|
||||
}
|
||||
else if (GlobalArgs.measure)
|
||||
{
|
||||
double rate = rateFrame(frame);
|
||||
if (!cap.set(CAP_PROP_ZOOM, state.minFocusStep))
|
||||
{
|
||||
if (--GlobalArgs.breakLimit <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << rate << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if ((focus || GlobalArgs.measure) && GlobalArgs.verbose)
|
||||
{
|
||||
cout << "STATE\t" << state << endl;
|
||||
cout << "Output from camera: " << endl
|
||||
<< (const char *) (intptr_t) cap.get(CAP_PROP_GPHOTO2_FLUSH_MSGS) << endl;
|
||||
}
|
||||
|
||||
imshow(windowOriginal, frame);
|
||||
switch (key = static_cast<char>(waitKey(30)))
|
||||
{
|
||||
case 'k': // focus out
|
||||
cap.set(CAP_PROP_ZOOM, 100);
|
||||
break;
|
||||
case 'j': // focus in
|
||||
cap.set(CAP_PROP_ZOOM, -100);
|
||||
break;
|
||||
case ',': // Drive to closest
|
||||
focusDriveEnd(cap, -FOCUS_DIRECTION_INFTY);
|
||||
break;
|
||||
case '.': // Drive to infinity
|
||||
focusDriveEnd(cap, FOCUS_DIRECTION_INFTY);
|
||||
break;
|
||||
case 'r': // reset focus state
|
||||
focus = true;
|
||||
state = createInitialState();
|
||||
break;
|
||||
case 'f': // focus switch on/off
|
||||
focus ^= true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (GlobalArgs.verbose)
|
||||
{
|
||||
cout << "Captured " << (int) cap.get(CAP_PROP_FRAME_COUNT) << " frames"
|
||||
<< endl << "in " << (int) (cap.get(CAP_PROP_POS_MSEC) / 1e2)
|
||||
<< " seconds," << endl << "at avg speed "
|
||||
<< (cap.get(CAP_PROP_FPS)) << " fps." << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user