mirror of
https://github.com/opencv/opencv.git
synced 2026-07-22 03:43:03 +04:00
Compare commits
151 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 59975db6a4 | |||
| ec2ff7f0c0 | |||
| 5d038686b1 | |||
| 6084901610 | |||
| e58c28974b | |||
| 1b4bd6a905 | |||
| 67fe57a0a3 | |||
| db0ae2ca50 | |||
| de164b0ccf | |||
| 194f1beae8 | |||
| 3bd6912e01 | |||
| 1a41ed2fda | |||
| 9d71c19939 | |||
| 5b73f3a316 | |||
| 96d747f030 | |||
| 5164c4ba31 | |||
| 13858cd561 | |||
| 772d9689e9 | |||
| ff3bb9f4e6 | |||
| e90b697cb0 | |||
| 70bc268c1a | |||
| b6d8c9d990 | |||
| a7ce9a176b | |||
| 52ba3778e3 | |||
| c7b6353a3c | |||
| 34b3d31f54 | |||
| 6f139b4f8e | |||
| 86a725933a | |||
| 64f02aa72d | |||
| 12a8f5486d | |||
| 97ac59cb73 | |||
| 762965897a | |||
| ea3746bd15 | |||
| ef2a376baf | |||
| dc8bb23a7d | |||
| 24361733e4 | |||
| b5fbb2b1c8 | |||
| b8ce65bec8 | |||
| 96903dc4ad | |||
| da669569e1 | |||
| eb40afa26a | |||
| 421fcf9e35 | |||
| d142c05d61 | |||
| 9a5d7f1a0b | |||
| 9d49cef29e | |||
| 1fbc6ab05d | |||
| 93c4dfb16d | |||
| 52b9207105 | |||
| d2e451e877 | |||
| 00e91fd3d0 | |||
| afc62f076a | |||
| 9c4204b89e | |||
| 3afb5a6006 | |||
| 7e44faf635 | |||
| 8cfc87cf01 | |||
| ea049e147d | |||
| 60f73eee7e | |||
| c1f3c41bab | |||
| d29eb2938c | |||
| a61b19b524 | |||
| 25b4d8a1b5 | |||
| aaa30dc5b6 | |||
| e0f426f78b | |||
| 8a09d95eab | |||
| 068769263e | |||
| 21e9edd1a3 | |||
| 544824ffc1 | |||
| d6e2097435 | |||
| cf43790a27 | |||
| 69eaa89e22 | |||
| e835878661 | |||
| 912592de4c | |||
| 85793d0138 | |||
| a57b03c356 | |||
| 5a5378b3bf | |||
| f01f1bc5e6 | |||
| 85c7190e41 | |||
| f2e4bec925 | |||
| 4a8d1147c2 | |||
| bb1c2d71a8 | |||
| be565c2235 | |||
| 389f176a67 | |||
| 5c21ca2697 | |||
| 4f5d585184 | |||
| c01fd16291 | |||
| 537d1322b4 | |||
| 8a803865cf | |||
| 6e22020dad | |||
| f91ada572a | |||
| f7c8f74ac1 | |||
| c4e80952ce | |||
| 178ed63e1a | |||
| 46edb54ac3 | |||
| 7cb78451d1 | |||
| 2897da037e | |||
| 4fa14f75b8 | |||
| 0886f6fe62 | |||
| 07a58c47cb | |||
| 8e40becab1 | |||
| 60eda6f25c | |||
| 2e78a3e5e9 | |||
| 966d35a9fb | |||
| 42447a7610 | |||
| ca50969c2b | |||
| 2d3e170370 | |||
| 8a37fc8223 | |||
| a5c20f8592 | |||
| 96a2edb375 | |||
| 15b313ce4b | |||
| 1ea6568951 | |||
| 56654ae360 | |||
| 9a3e53e738 | |||
| 2243bfa181 | |||
| 33cd7f38a8 | |||
| 2fc0ce5c24 | |||
| c5d009d6c4 | |||
| 7d28541bbe | |||
| e6f3f3c029 | |||
| 7746d9b7cc | |||
| 3494d640df | |||
| c22cc67ba8 | |||
| 558054a53d | |||
| c7b471f10f | |||
| f4ffcae8d9 | |||
| 0422054aa1 | |||
| a81f0a5123 | |||
| c36582d2df | |||
| d50c07e303 | |||
| 54693b3fa7 | |||
| 3c3bc123fc | |||
| ac33cd688c | |||
| b5e42d8cc1 | |||
| 7e4e8921bc | |||
| 6dcd455ac4 | |||
| 1d58e1a14a | |||
| d122510c4f | |||
| 6613d14261 | |||
| a14e524b32 | |||
| 226ff93917 | |||
| d28e6c9b36 | |||
| c16f465ff5 | |||
| 3231c2f995 | |||
| 16bcc30e42 | |||
| 69c50e0181 | |||
| 486c40f578 | |||
| 08e38e9ff9 | |||
| ba3b902da7 | |||
| bf94e6a91c | |||
| ecc53dd7a4 | |||
| fc0e0239b8 | |||
| d0210f510e |
Vendored
+1
-1
@@ -26,7 +26,7 @@ if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
endif()
|
||||
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wcast-align -Wshadow -Wunused)
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter) # clang
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter -Wshift-negative-value) # clang
|
||||
|
||||
set_target_properties(${JPEG_LIBRARY}
|
||||
PROPERTIES OUTPUT_NAME ${JPEG_LIBRARY}
|
||||
|
||||
Vendored
+1
-1
@@ -82,7 +82,7 @@ if(UNIX)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wshorten-64-to-32 -Wattributes -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations)
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wshorten-64-to-32 -Wattributes -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wshift-negative-value)
|
||||
|
||||
set_target_properties(${ZLIB_LIBRARY} PROPERTIES
|
||||
OUTPUT_NAME ${ZLIB_LIBRARY}
|
||||
|
||||
+6
-2
@@ -140,7 +140,7 @@ OCV_OPTION(WITH_1394 "Include IEEE1394 support" ON
|
||||
OCV_OPTION(WITH_AVFOUNDATION "Use AVFoundation for Video I/O" ON IF IOS)
|
||||
OCV_OPTION(WITH_CARBON "Use Carbon for UI instead of Cocoa" OFF IF APPLE )
|
||||
OCV_OPTION(WITH_CUDA "Include NVidia Cuda Runtime support" ON IF (CMAKE_VERSION VERSION_GREATER "2.8" AND NOT IOS) )
|
||||
OCV_OPTION(WITH_VTK "Include VTK library support (and build opencv_viz module eiher)" OFF IF (NOT ANDROID AND NOT IOS) )
|
||||
OCV_OPTION(WITH_VTK "Include VTK library support (and build opencv_viz module eiher)" OFF IF (NOT ANDROID AND NOT IOS AND NOT CMAKE_CROSSCOMPILING) )
|
||||
OCV_OPTION(WITH_CUFFT "Include NVidia Cuda Fast Fourier Transform (FFT) library support" ON IF (CMAKE_VERSION VERSION_GREATER "2.8" AND NOT IOS) )
|
||||
OCV_OPTION(WITH_CUBLAS "Include NVidia Cuda Basic Linear Algebra Subprograms (BLAS) library support" OFF IF (CMAKE_VERSION VERSION_GREATER "2.8" AND NOT IOS) )
|
||||
OCV_OPTION(WITH_NVCUVID "Include NVidia Video Decoding library support" OFF IF (CMAKE_VERSION VERSION_GREATER "2.8" AND NOT ANDROID AND NOT IOS AND NOT APPLE) )
|
||||
@@ -631,7 +631,11 @@ if(INSTALL_TESTS AND OPENCV_TEST_DATA_PATH)
|
||||
if(BUILD_opencv_python)
|
||||
file(GLOB py_tests modules/python/test/*.py)
|
||||
install(PROGRAMS ${py_tests} DESTINATION ${OPENCV_TEST_INSTALL_PATH} COMPONENT tests)
|
||||
set(OPENCV_PYTHON_TESTS_LIST "test2.py")
|
||||
if(BUILD_opencv_nonfree)
|
||||
file(GLOB py_nonfree_tests modules/python/test/nonfree_tests/*.py)
|
||||
install(PROGRAMS ${py_nonfree_tests} DESTINATION ${OPENCV_TEST_INSTALL_PATH}/nonfree_tests COMPONENT tests)
|
||||
endif()
|
||||
set(OPENCV_PYTHON_TESTS_LIST "test.py")
|
||||
endif()
|
||||
if(WIN32)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/opencv_run_all_tests_windows.cmd.in"
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
### OpenCV: Open Source Computer Vision Library
|
||||
|
||||
[](https://www.gittip.com/OpenCV/)
|
||||
|
||||
#### Resources
|
||||
|
||||
* Homepage: <http://opencv.org>
|
||||
|
||||
@@ -3,3 +3,4 @@ link_libraries(${OPENCV_LINKER_LIBS})
|
||||
add_subdirectory(haartraining)
|
||||
add_subdirectory(traincascade)
|
||||
add_subdirectory(annotation)
|
||||
add_subdirectory(visualisation)
|
||||
|
||||
@@ -20,7 +20,6 @@ set_target_properties(${the_target} PROPERTIES
|
||||
DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}"
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}
|
||||
RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}
|
||||
INSTALL_NAME_DIR lib
|
||||
OUTPUT_NAME "opencv_annotation")
|
||||
|
||||
if(ENABLE_SOLUTION_FOLDERS)
|
||||
|
||||
@@ -46,6 +46,9 @@ USAGE:
|
||||
./opencv_annotation -images <folder location> -annotations <ouput file>
|
||||
|
||||
Created by: Puttemans Steven - February 2015
|
||||
Adapted by: Puttemans Steven - April 2016 - Vectorize the process to enable better processing
|
||||
+ early leave and store by pressing an ESC key
|
||||
+ enable delete `d` button, to remove last annotation
|
||||
*****************************************************************************************************/
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
@@ -66,16 +69,15 @@ using namespace cv;
|
||||
|
||||
// Function prototypes
|
||||
void on_mouse(int, int, int, int, void*);
|
||||
string int2string(int);
|
||||
void get_annotations(Mat, stringstream*);
|
||||
vector<Rect> get_annotations(Mat);
|
||||
|
||||
// Public parameters
|
||||
Mat image;
|
||||
int roi_x0 = 0, roi_y0 = 0, roi_x1 = 0, roi_y1 = 0, num_of_rec = 0;
|
||||
bool start_draw = false;
|
||||
bool start_draw = false, stop = false;
|
||||
|
||||
// Window name for visualisation purposes
|
||||
const string window_name="OpenCV Based Annotation Tool";
|
||||
const string window_name = "OpenCV Based Annotation Tool";
|
||||
|
||||
// FUNCTION : Mouse response for selecting objects in images
|
||||
// If left button is clicked, start drawing a rectangle as long as mouse moves
|
||||
@@ -83,7 +85,7 @@ const string window_name="OpenCV Based Annotation Tool";
|
||||
void on_mouse(int event, int x, int y, int , void * )
|
||||
{
|
||||
// Action when left button is clicked
|
||||
if(event == CV_EVENT_LBUTTONDOWN)
|
||||
if(event == EVENT_LBUTTONDOWN)
|
||||
{
|
||||
if(!start_draw)
|
||||
{
|
||||
@@ -96,8 +98,9 @@ void on_mouse(int event, int x, int y, int , void * )
|
||||
start_draw = false;
|
||||
}
|
||||
}
|
||||
// Action when mouse is moving
|
||||
if((event == CV_EVENT_MOUSEMOVE) && start_draw)
|
||||
|
||||
// Action when mouse is moving and drawing is enabled
|
||||
if((event == EVENT_MOUSEMOVE) && start_draw)
|
||||
{
|
||||
// Redraw bounding box for annotation
|
||||
Mat current_view;
|
||||
@@ -107,75 +110,88 @@ void on_mouse(int event, int x, int y, int , void * )
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION : snippet to convert an integer value to a string using a clean function
|
||||
// instead of creating a stringstream each time inside the main code
|
||||
string int2string(int num)
|
||||
// FUNCTION : returns a vector of Rect objects given an image containing positive object instances
|
||||
vector<Rect> get_annotations(Mat input_image)
|
||||
{
|
||||
stringstream temp_stream;
|
||||
temp_stream << num;
|
||||
return temp_stream.str();
|
||||
}
|
||||
vector<Rect> current_annotations;
|
||||
|
||||
// FUNCTION : given an image containing positive object instances, add all the object
|
||||
// annotations to a known stringstream
|
||||
void get_annotations(Mat input_image, stringstream* output_stream)
|
||||
{
|
||||
// Make it possible to exit the annotation
|
||||
bool stop = false;
|
||||
|
||||
// Reset the num_of_rec element at each iteration
|
||||
// Make sure the global image is set to the current image
|
||||
num_of_rec = 0;
|
||||
image = input_image;
|
||||
// Make it possible to exit the annotation process
|
||||
stop = false;
|
||||
|
||||
// Init window interface and couple mouse actions
|
||||
namedWindow(window_name, WINDOW_AUTOSIZE);
|
||||
setMouseCallback(window_name, on_mouse);
|
||||
|
||||
image = input_image;
|
||||
imshow(window_name, image);
|
||||
stringstream temp_stream;
|
||||
int key_pressed = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// Get a temporary image clone
|
||||
Mat temp_image = input_image.clone();
|
||||
Rect currentRect(0, 0, 0, 0);
|
||||
|
||||
// Keys for processing
|
||||
// You need to select one for confirming a selection and one to continue to the next image
|
||||
// Based on the universal ASCII code of the keystroke: http://www.asciitable.com/
|
||||
// c = 99 add rectangle to current image
|
||||
// n = 110 save added rectangles and show next image
|
||||
// <ESC> = 27 exit program
|
||||
// <c> = 99 add rectangle to current image
|
||||
// <n> = 110 save added rectangles and show next image
|
||||
// <d> = 100 delete the last annotation made
|
||||
// <ESC> = 27 exit program
|
||||
key_pressed = 0xFF & waitKey(0);
|
||||
switch( key_pressed )
|
||||
{
|
||||
case 27:
|
||||
destroyWindow(window_name);
|
||||
stop = true;
|
||||
break;
|
||||
case 99:
|
||||
// Add a rectangle to the list
|
||||
num_of_rec++;
|
||||
// Draw initiated from top left corner
|
||||
if(roi_x0<roi_x1 && roi_y0<roi_y1)
|
||||
{
|
||||
temp_stream << " " << int2string(roi_x0) << " " << int2string(roi_y0) << " " << int2string(roi_x1-roi_x0) << " " << int2string(roi_y1-roi_y0);
|
||||
currentRect.x = roi_x0;
|
||||
currentRect.y = roi_y0;
|
||||
currentRect.width = roi_x1-roi_x0;
|
||||
currentRect.height = roi_y1-roi_y0;
|
||||
}
|
||||
// Draw initiated from bottom right corner
|
||||
if(roi_x0>roi_x1 && roi_y0>roi_y1)
|
||||
{
|
||||
temp_stream << " " << int2string(roi_x1) << " " << int2string(roi_y1) << " " << int2string(roi_x0-roi_x1) << " " << int2string(roi_y0-roi_y1);
|
||||
currentRect.x = roi_x1;
|
||||
currentRect.y = roi_y1;
|
||||
currentRect.width = roi_x0-roi_x1;
|
||||
currentRect.height = roi_y0-roi_y1;
|
||||
}
|
||||
// Draw initiated from top right corner
|
||||
if(roi_x0>roi_x1 && roi_y0<roi_y1)
|
||||
{
|
||||
temp_stream << " " << int2string(roi_x1) << " " << int2string(roi_y0) << " " << int2string(roi_x0-roi_x1) << " " << int2string(roi_y1-roi_y0);
|
||||
currentRect.x = roi_x1;
|
||||
currentRect.y = roi_y0;
|
||||
currentRect.width = roi_x0-roi_x1;
|
||||
currentRect.height = roi_y1-roi_y0;
|
||||
}
|
||||
// Draw initiated from bottom left corner
|
||||
if(roi_x0<roi_x1 && roi_y0>roi_y1)
|
||||
{
|
||||
temp_stream << " " << int2string(roi_x0) << " " << int2string(roi_y1) << " " << int2string(roi_x1-roi_x0) << " " << int2string(roi_y0-roi_y1);
|
||||
currentRect.x = roi_x0;
|
||||
currentRect.y = roi_y1;
|
||||
currentRect.width = roi_x1-roi_x0;
|
||||
currentRect.height = roi_y0-roi_y1;
|
||||
}
|
||||
|
||||
rectangle(input_image, Point(roi_x0,roi_y0), Point(roi_x1,roi_y1), Scalar(0,255,0), 1);
|
||||
|
||||
// Draw the rectangle on the canvas
|
||||
// Add the rectangle to the vector of annotations
|
||||
current_annotations.push_back(currentRect);
|
||||
break;
|
||||
case 100:
|
||||
// Remove the last annotation
|
||||
if(current_annotations.size() > 0){
|
||||
current_annotations.pop_back();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Default case --> do nothing at all
|
||||
// Other keystrokes can simply be ignored
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -184,35 +200,40 @@ void get_annotations(Mat input_image, stringstream* output_stream)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Draw all the current rectangles onto the top image and make sure that the global image is linked
|
||||
for(int i=0; i < (int)current_annotations.size(); i++){
|
||||
rectangle(temp_image, current_annotations[i], Scalar(0,255,0), 1);
|
||||
}
|
||||
image = temp_image;
|
||||
|
||||
// Force an explicit redraw of the canvas --> necessary to visualize delete correctly
|
||||
imshow(window_name, image);
|
||||
}
|
||||
// Continue as long as the next image key has not been pressed
|
||||
while(key_pressed != 110);
|
||||
|
||||
// If there are annotations AND the next image key is pressed
|
||||
// Write the image annotations to the file
|
||||
if(num_of_rec>0 && key_pressed==110)
|
||||
{
|
||||
*output_stream << " " << num_of_rec << temp_stream.str() << endl;
|
||||
}
|
||||
|
||||
// Close down the window
|
||||
destroyWindow(window_name);
|
||||
|
||||
// Return the data
|
||||
return current_annotations;
|
||||
}
|
||||
|
||||
int main( int argc, const char** argv )
|
||||
{
|
||||
// If no arguments are given, then supply some information on how this tool works
|
||||
if( argc == 1 ){
|
||||
cout << "Usage: " << argv[0] << endl;
|
||||
cout << " -images <folder_location> [example - /data/testimages/]" << endl;
|
||||
cout << " -annotations <ouput_file> [example - /data/annotations.txt]" << endl;
|
||||
|
||||
return -1;
|
||||
cout << "Usage: " << argv[0] << endl;
|
||||
cout << " -images <folder_location> [example - /data/testimages/]" << endl;
|
||||
cout << " -annotations <ouput_file> [example - /data/annotations.txt]" << endl;
|
||||
cout << "TIP: Use absolute paths to avoid any problems with the software!" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Read in the input arguments
|
||||
string image_folder;
|
||||
string annotations;
|
||||
string annotations_file;
|
||||
for(int i = 1; i < argc; ++i )
|
||||
{
|
||||
if( !strcmp( argv[i], "-images" ) )
|
||||
@@ -221,7 +242,7 @@ int main( int argc, const char** argv )
|
||||
}
|
||||
else if( !strcmp( argv[i], "-annotations" ) )
|
||||
{
|
||||
annotations = argv[++i];
|
||||
annotations_file = argv[++i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,14 +267,9 @@ int main( int argc, const char** argv )
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create the outputfilestream
|
||||
ofstream output(annotations.c_str());
|
||||
if ( !output.is_open() ){
|
||||
cerr << "The path for the output file contains an error and could not be opened. Please check again!" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Start by processing the data
|
||||
// Return the image filenames inside the image folder
|
||||
vector< vector<Rect> > annotations;
|
||||
vector<String> filenames;
|
||||
String folder(image_folder);
|
||||
glob(folder, filenames);
|
||||
@@ -271,15 +287,33 @@ int main( int argc, const char** argv )
|
||||
continue;
|
||||
}
|
||||
|
||||
// Perform annotations & generate corresponding output
|
||||
stringstream output_stream;
|
||||
get_annotations(current_image, &output_stream);
|
||||
// Perform annotations & store the result inside the vectorized structure
|
||||
vector<Rect> current_annotations = get_annotations(current_image);
|
||||
annotations.push_back(current_annotations);
|
||||
|
||||
// Store the annotations, write to the output file
|
||||
if (output_stream.str() != ""){
|
||||
output << filenames[i] << output_stream.str();
|
||||
// Check if the ESC key was hit, then exit earlier then expected
|
||||
if(stop){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// When all data is processed, store the data gathered inside the proper file
|
||||
// This now even gets called when the ESC button was hit to store preliminary results
|
||||
ofstream output(annotations_file.c_str());
|
||||
if ( !output.is_open() ){
|
||||
cerr << "The path for the output file contains an error and could not be opened. Please check again!" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Store the annotations, write to the output file
|
||||
for(int i = 0; i < (int)annotations.size(); i++){
|
||||
output << filenames[i] << " " << annotations[i].size();
|
||||
for(int j=0; j < (int)annotations[i].size(); j++){
|
||||
Rect temp = annotations[i][j];
|
||||
output << " " << temp.x << " " << temp.y << " " << temp.width << " " << temp.height;
|
||||
}
|
||||
output << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ set_target_properties(opencv_haartraining_engine PROPERTIES
|
||||
DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}"
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}
|
||||
RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}
|
||||
INSTALL_NAME_DIR lib
|
||||
)
|
||||
|
||||
# -----------------------------------------------------------
|
||||
|
||||
@@ -26,7 +26,6 @@ set_target_properties(${the_target} PROPERTIES
|
||||
DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}"
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}
|
||||
RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}
|
||||
INSTALL_NAME_DIR lib
|
||||
OUTPUT_NAME "opencv_traincascade")
|
||||
|
||||
if(ENABLE_SOLUTION_FOLDERS)
|
||||
|
||||
@@ -191,6 +191,7 @@ bool CvCascadeClassifier::train( const string _cascadeDirName,
|
||||
cascadeParams.printAttrs();
|
||||
stageParams->printAttrs();
|
||||
featureParams->printAttrs();
|
||||
cout << "Number of unique features given windowSize [" << _cascadeParams.winSize.width << "," << _cascadeParams.winSize.height << "] : " << featureEvaluator->getNumFeatures() << "" << endl;
|
||||
|
||||
int startNumStages = (int)stageClassifiers.size();
|
||||
if ( startNumStages > 1 )
|
||||
@@ -336,7 +337,7 @@ int CvCascadeClassifier::fillPassedSamples( int first, int count, bool isPositiv
|
||||
consumed++;
|
||||
|
||||
featureEvaluator->setImage( img, isPositive ? 1 : 0, i );
|
||||
if( predict( i ) == 1.0F )
|
||||
if( predict( i ) == 1 )
|
||||
{
|
||||
getcount++;
|
||||
printf("%s current samples: %d\r", isPositive ? "POS":"NEG", getcount);
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
SET(OPENCV_VISUALISATION_DEPS opencv_core opencv_highgui opencv_imgproc)
|
||||
ocv_check_dependencies(${OPENCV_VISUALISATION_DEPS})
|
||||
|
||||
if(NOT OCV_DEPENDENCIES_FOUND)
|
||||
return()
|
||||
endif()
|
||||
|
||||
project(visualisation)
|
||||
|
||||
ocv_include_directories("${CMAKE_CURRENT_SOURCE_DIR}" "${OpenCV_SOURCE_DIR}/include/opencv")
|
||||
ocv_include_modules(${OPENCV_VISUALISATION_DEPS})
|
||||
|
||||
set(visualisation_files opencv_visualisation.cpp)
|
||||
set(the_target opencv_visualisation)
|
||||
|
||||
add_executable(${the_target} ${visualisation_files})
|
||||
target_link_libraries(${the_target} ${OPENCV_VISUALISATION_DEPS})
|
||||
|
||||
set_target_properties(${the_target} PROPERTIES
|
||||
DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}"
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}
|
||||
RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}
|
||||
OUTPUT_NAME "opencv_visualisation")
|
||||
|
||||
if(ENABLE_SOLUTION_FOLDERS)
|
||||
set_target_properties(${the_target} PROPERTIES FOLDER "applications")
|
||||
endif()
|
||||
|
||||
if(INSTALL_CREATE_DISTRIB)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
install(TARGETS ${the_target} RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} CONFIGURATIONS Release COMPONENT dev)
|
||||
endif()
|
||||
else()
|
||||
install(TARGETS ${the_target} RUNTIME DESTINATION ${OPENCV_BIN_INSTALL_PATH} COMPONENT dev)
|
||||
endif()
|
||||
@@ -0,0 +1,350 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// 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 Intel Corporation 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*****************************************************************************************************
|
||||
|
||||
Software for visualising cascade classifier models trained by OpenCV and to get a better
|
||||
understanding of the used features.
|
||||
|
||||
USAGE:
|
||||
./visualise_models -model <model.xml> -image <ref.png> -data <output folder>
|
||||
|
||||
LIMITS
|
||||
- Use an absolute path for the output folder to ensure the tool works
|
||||
- Only handles cascade classifier models
|
||||
- Handles stumps only for the moment
|
||||
- Needs a valid training/test sample window with the original model dimensions, passed as `ref.png`
|
||||
- Can handle HAAR and LBP features
|
||||
|
||||
Created by: Puttemans Steven - April 2016
|
||||
*****************************************************************************************************/
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
#include <opencv2/imgproc/imgproc.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
struct rect_data{
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
float weight;
|
||||
};
|
||||
|
||||
int main( int argc, const char** argv )
|
||||
{
|
||||
// Read in the input arguments
|
||||
string model = "";
|
||||
string output_folder = "";
|
||||
string image_ref = "";
|
||||
for(int i = 1; i < argc; ++i )
|
||||
{
|
||||
if( !strcmp( argv[i], "-model" ) )
|
||||
{
|
||||
model = argv[++i];
|
||||
}else if( !strcmp( argv[i], "-image" ) ){
|
||||
image_ref = argv[++i];
|
||||
}else if( !strcmp( argv[i], "-data" ) ){
|
||||
output_folder = argv[++i];
|
||||
}
|
||||
}
|
||||
|
||||
// Value for timing
|
||||
// You can increase this to have a better visualisation during the generation
|
||||
int timing = 1;
|
||||
|
||||
// Value for cols of storing elements
|
||||
int cols_prefered = 5;
|
||||
|
||||
// Open the XML model
|
||||
FileStorage fs;
|
||||
fs.open(model, FileStorage::READ);
|
||||
|
||||
// Get a the required information
|
||||
// First decide which feature type we are using
|
||||
FileNode cascade = fs["cascade"];
|
||||
string feature_type = cascade["featureType"];
|
||||
bool haar = false, lbp = false;
|
||||
if (feature_type.compare("HAAR") == 0){
|
||||
haar = true;
|
||||
}
|
||||
if (feature_type.compare("LBP") == 0){
|
||||
lbp = true;
|
||||
}
|
||||
if ( feature_type.compare("HAAR") != 0 && feature_type.compare("LBP")){
|
||||
cerr << "The model is not an HAAR or LBP feature based model!" << endl;
|
||||
cerr << "Please select a model that can be visualized by the software." << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// We make a visualisation mask - which increases the window to make it at least a bit more visible
|
||||
int resize_factor = 10;
|
||||
int resize_storage_factor = 10;
|
||||
Mat reference_image = imread(image_ref, IMREAD_GRAYSCALE );
|
||||
Mat visualization;
|
||||
resize(reference_image, visualization, Size(reference_image.cols * resize_factor, reference_image.rows * resize_factor));
|
||||
|
||||
// First recover for each stage the number of weak features and their index
|
||||
// Important since it is NOT sequential when using LBP features
|
||||
vector< vector<int> > stage_features;
|
||||
FileNode stages = cascade["stages"];
|
||||
FileNodeIterator it_stages = stages.begin(), it_stages_end = stages.end();
|
||||
int idx = 0;
|
||||
for( ; it_stages != it_stages_end; it_stages++, idx++ ){
|
||||
vector<int> current_feature_indexes;
|
||||
FileNode weak_classifiers = (*it_stages)["weakClassifiers"];
|
||||
FileNodeIterator it_weak = weak_classifiers.begin(), it_weak_end = weak_classifiers.end();
|
||||
vector<int> values;
|
||||
for(int idy = 0; it_weak != it_weak_end; it_weak++, idy++ ){
|
||||
(*it_weak)["internalNodes"] >> values;
|
||||
current_feature_indexes.push_back( (int)values[2] );
|
||||
}
|
||||
stage_features.push_back(current_feature_indexes);
|
||||
}
|
||||
|
||||
// If the output option has been chosen than we will store a combined image plane for
|
||||
// each stage, containing all weak classifiers for that stage.
|
||||
bool draw_planes = false;
|
||||
stringstream output_video;
|
||||
output_video << output_folder << "model_visualization.avi";
|
||||
VideoWriter result_video;
|
||||
if( output_folder.compare("") != 0 ){
|
||||
draw_planes = true;
|
||||
result_video.open(output_video.str(), CV_FOURCC('X','V','I','D'), 15, Size(reference_image.cols * resize_factor, reference_image.rows * resize_factor), false);
|
||||
}
|
||||
|
||||
if(haar){
|
||||
// Grab the corresponding features dimensions and weights
|
||||
FileNode features = cascade["features"];
|
||||
vector< vector< rect_data > > feature_data;
|
||||
FileNodeIterator it_features = features.begin(), it_features_end = features.end();
|
||||
for(int idf = 0; it_features != it_features_end; it_features++, idf++ ){
|
||||
vector< rect_data > current_feature_rectangles;
|
||||
FileNode rectangles = (*it_features)["rects"];
|
||||
int nrects = (int)rectangles.size();
|
||||
for(int k = 0; k < nrects; k++){
|
||||
rect_data current_data;
|
||||
FileNode single_rect = rectangles[k];
|
||||
current_data.x = (int)single_rect[0];
|
||||
current_data.y = (int)single_rect[1];
|
||||
current_data.w = (int)single_rect[2];
|
||||
current_data.h = (int)single_rect[3];
|
||||
current_data.weight = (float)single_rect[4];
|
||||
current_feature_rectangles.push_back(current_data);
|
||||
}
|
||||
feature_data.push_back(current_feature_rectangles);
|
||||
}
|
||||
|
||||
// Loop over each possible feature on its index, visualise on the mask and wait a bit,
|
||||
// then continue to the next feature.
|
||||
// If visualisations should be stored then do the in between calculations
|
||||
Mat image_plane;
|
||||
Mat metadata = Mat::zeros(150, 1000, CV_8UC1);
|
||||
vector< rect_data > current_rects;
|
||||
for(int sid = 0; sid < (int)stage_features.size(); sid ++){
|
||||
if(draw_planes){
|
||||
int features_nmbr = (int)stage_features[sid].size();
|
||||
int cols = cols_prefered;
|
||||
int rows = features_nmbr / cols;
|
||||
if( (features_nmbr % cols) > 0){
|
||||
rows++;
|
||||
}
|
||||
image_plane = Mat::zeros(reference_image.rows * resize_storage_factor * rows, reference_image.cols * resize_storage_factor * cols, CV_8UC1);
|
||||
}
|
||||
for(int fid = 0; fid < (int)stage_features[sid].size(); fid++){
|
||||
stringstream meta1, meta2;
|
||||
meta1 << "Stage " << sid << " / Feature " << fid;
|
||||
meta2 << "Rectangles: ";
|
||||
Mat temp_window = visualization.clone();
|
||||
Mat temp_metadata = metadata.clone();
|
||||
int current_feature_index = stage_features[sid][fid];
|
||||
current_rects = feature_data[current_feature_index];
|
||||
Mat single_feature = reference_image.clone();
|
||||
resize(single_feature, single_feature, Size(), resize_storage_factor, resize_storage_factor);
|
||||
for(int i = 0; i < (int)current_rects.size(); i++){
|
||||
rect_data local = current_rects[i];
|
||||
if(draw_planes){
|
||||
if(local.weight >= 0){
|
||||
rectangle(single_feature, Rect(local.x * resize_storage_factor, local.y * resize_storage_factor, local.w * resize_storage_factor, local.h * resize_storage_factor), Scalar(0), CV_FILLED);
|
||||
}else{
|
||||
rectangle(single_feature, Rect(local.x * resize_storage_factor, local.y * resize_storage_factor, local.w * resize_storage_factor, local.h * resize_storage_factor), Scalar(255), CV_FILLED);
|
||||
}
|
||||
}
|
||||
Rect part(local.x * resize_factor, local.y * resize_factor, local.w * resize_factor, local.h * resize_factor);
|
||||
meta2 << part << " (w " << local.weight << ") ";
|
||||
if(local.weight >= 0){
|
||||
rectangle(temp_window, part, Scalar(0), CV_FILLED);
|
||||
}else{
|
||||
rectangle(temp_window, part, Scalar(255), CV_FILLED);
|
||||
}
|
||||
}
|
||||
imshow("features", temp_window);
|
||||
putText(temp_window, meta1.str(), Point(15,15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255));
|
||||
result_video.write(temp_window);
|
||||
// Copy the feature image if needed
|
||||
if(draw_planes){
|
||||
single_feature.copyTo(image_plane(Rect(0 + (fid%cols_prefered)*single_feature.cols, 0 + (fid/cols_prefered) * single_feature.rows, single_feature.cols, single_feature.rows)));
|
||||
}
|
||||
putText(temp_metadata, meta1.str(), Point(15,15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255));
|
||||
putText(temp_metadata, meta2.str(), Point(15,40), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255));
|
||||
imshow("metadata", temp_metadata);
|
||||
waitKey(timing);
|
||||
}
|
||||
//Store the stage image if needed
|
||||
if(draw_planes){
|
||||
stringstream save_location;
|
||||
save_location << output_folder << "stage_" << sid << ".png";
|
||||
imwrite(save_location.str(), image_plane);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(lbp){
|
||||
// Grab the corresponding features dimensions and weights
|
||||
FileNode features = cascade["features"];
|
||||
vector<Rect> feature_data;
|
||||
FileNodeIterator it_features = features.begin(), it_features_end = features.end();
|
||||
for(int idf = 0; it_features != it_features_end; it_features++, idf++ ){
|
||||
FileNode rectangle = (*it_features)["rect"];
|
||||
Rect current_feature ((int)rectangle[0], (int)rectangle[1], (int)rectangle[2], (int)rectangle[3]);
|
||||
feature_data.push_back(current_feature);
|
||||
}
|
||||
|
||||
// Loop over each possible feature on its index, visualise on the mask and wait a bit,
|
||||
// then continue to the next feature.
|
||||
Mat image_plane;
|
||||
Mat metadata = Mat::zeros(150, 1000, CV_8UC1);
|
||||
for(int sid = 0; sid < (int)stage_features.size(); sid ++){
|
||||
if(draw_planes){
|
||||
int features_nmbr = (int)stage_features[sid].size();
|
||||
int cols = cols_prefered;
|
||||
int rows = features_nmbr / cols;
|
||||
if( (features_nmbr % cols) > 0){
|
||||
rows++;
|
||||
}
|
||||
image_plane = Mat::zeros(reference_image.rows * resize_storage_factor * rows, reference_image.cols * resize_storage_factor * cols, CV_8UC1);
|
||||
}
|
||||
for(int fid = 0; fid < (int)stage_features[sid].size(); fid++){
|
||||
stringstream meta1, meta2;
|
||||
meta1 << "Stage " << sid << " / Feature " << fid;
|
||||
meta2 << "Rectangle: ";
|
||||
Mat temp_window = visualization.clone();
|
||||
Mat temp_metadata = metadata.clone();
|
||||
int current_feature_index = stage_features[sid][fid];
|
||||
Rect current_rect = feature_data[current_feature_index];
|
||||
Mat single_feature = reference_image.clone();
|
||||
resize(single_feature, single_feature, Size(), resize_storage_factor, resize_storage_factor);
|
||||
|
||||
// VISUALISATION
|
||||
// The rectangle is the top left one of a 3x3 block LBP constructor
|
||||
Rect resized(current_rect.x * resize_factor, current_rect.y * resize_factor, current_rect.width * resize_factor, current_rect.height * resize_factor);
|
||||
meta2 << resized;
|
||||
// Top left
|
||||
rectangle(temp_window, resized, Scalar(255), 1);
|
||||
// Top middle
|
||||
rectangle(temp_window, Rect(resized.x + resized.width, resized.y, resized.width, resized.height), Scalar(255), 1);
|
||||
// Top right
|
||||
rectangle(temp_window, Rect(resized.x + 2*resized.width, resized.y, resized.width, resized.height), Scalar(255), 1);
|
||||
// Middle left
|
||||
rectangle(temp_window, Rect(resized.x, resized.y + resized.height, resized.width, resized.height), Scalar(255), 1);
|
||||
// Middle middle
|
||||
rectangle(temp_window, Rect(resized.x + resized.width, resized.y + resized.height, resized.width, resized.height), Scalar(255), CV_FILLED);
|
||||
// Middle right
|
||||
rectangle(temp_window, Rect(resized.x + 2*resized.width, resized.y + resized.height, resized.width, resized.height), Scalar(255), 1);
|
||||
// Bottom left
|
||||
rectangle(temp_window, Rect(resized.x, resized.y + 2*resized.height, resized.width, resized.height), Scalar(255), 1);
|
||||
// Bottom middle
|
||||
rectangle(temp_window, Rect(resized.x + resized.width, resized.y + 2*resized.height, resized.width, resized.height), Scalar(255), 1);
|
||||
// Bottom right
|
||||
rectangle(temp_window, Rect(resized.x + 2*resized.width, resized.y + 2*resized.height, resized.width, resized.height), Scalar(255), 1);
|
||||
|
||||
if(draw_planes){
|
||||
Rect resized_inner(current_rect.x * resize_storage_factor, current_rect.y * resize_storage_factor, current_rect.width * resize_storage_factor, current_rect.height * resize_storage_factor);
|
||||
// Top left
|
||||
rectangle(single_feature, resized_inner, Scalar(255), 1);
|
||||
// Top middle
|
||||
rectangle(single_feature, Rect(resized_inner.x + resized_inner.width, resized_inner.y, resized_inner.width, resized_inner.height), Scalar(255), 1);
|
||||
// Top right
|
||||
rectangle(single_feature, Rect(resized_inner.x + 2*resized_inner.width, resized_inner.y, resized_inner.width, resized_inner.height), Scalar(255), 1);
|
||||
// Middle left
|
||||
rectangle(single_feature, Rect(resized_inner.x, resized_inner.y + resized_inner.height, resized_inner.width, resized_inner.height), Scalar(255), 1);
|
||||
// Middle middle
|
||||
rectangle(single_feature, Rect(resized_inner.x + resized_inner.width, resized_inner.y + resized_inner.height, resized_inner.width, resized_inner.height), Scalar(255), CV_FILLED);
|
||||
// Middle right
|
||||
rectangle(single_feature, Rect(resized_inner.x + 2*resized_inner.width, resized_inner.y + resized_inner.height, resized_inner.width, resized_inner.height), Scalar(255), 1);
|
||||
// Bottom left
|
||||
rectangle(single_feature, Rect(resized_inner.x, resized_inner.y + 2*resized_inner.height, resized_inner.width, resized_inner.height), Scalar(255), 1);
|
||||
// Bottom middle
|
||||
rectangle(single_feature, Rect(resized_inner.x + resized_inner.width, resized_inner.y + 2*resized_inner.height, resized_inner.width, resized_inner.height), Scalar(255), 1);
|
||||
// Bottom right
|
||||
rectangle(single_feature, Rect(resized_inner.x + 2*resized_inner.width, resized_inner.y + 2*resized_inner.height, resized_inner.width, resized_inner.height), Scalar(255), 1);
|
||||
|
||||
single_feature.copyTo(image_plane(Rect(0 + (fid%cols_prefered)*single_feature.cols, 0 + (fid/cols_prefered) * single_feature.rows, single_feature.cols, single_feature.rows)));
|
||||
}
|
||||
|
||||
putText(temp_metadata, meta1.str(), Point(15,15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255));
|
||||
putText(temp_metadata, meta2.str(), Point(15,40), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255));
|
||||
imshow("metadata", temp_metadata);
|
||||
imshow("features", temp_window);
|
||||
putText(temp_window, meta1.str(), Point(15,15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255));
|
||||
result_video.write(temp_window);
|
||||
|
||||
waitKey(timing);
|
||||
}
|
||||
|
||||
//Store the stage image if needed
|
||||
if(draw_planes){
|
||||
stringstream save_location;
|
||||
save_location << output_folder << "stage_" << sid << ".png";
|
||||
imwrite(save_location.str(), image_plane);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -35,7 +35,18 @@ if(CUDA_FOUND)
|
||||
|
||||
if(WITH_NVCUVID)
|
||||
find_cuda_helper_libs(nvcuvid)
|
||||
set(HAVE_NVCUVID 1)
|
||||
|
||||
if(WIN32)
|
||||
find_cuda_helper_libs(nvcuvenc)
|
||||
endif()
|
||||
|
||||
if(CUDA_nvcuvid_LIBRARY)
|
||||
set(HAVE_NVCUVID 1)
|
||||
endif()
|
||||
|
||||
if(CUDA_nvcuvenc_LIBRARY)
|
||||
set(HAVE_NVCUVENC 1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(STATUS "CUDA detected: " ${CUDA_VERSION})
|
||||
|
||||
@@ -65,6 +65,8 @@ if(NOT HAVE_TBB)
|
||||
set(_TBB_LIB_PATH "${_TBB_LIB_PATH}/vc11")
|
||||
elseif(MSVC12)
|
||||
set(_TBB_LIB_PATH "${_TBB_LIB_PATH}/vc12")
|
||||
elseif(MSVC14)
|
||||
set(_TBB_LIB_PATH "${_TBB_LIB_PATH}/vc14")
|
||||
endif()
|
||||
set(TBB_LIB_DIR "${_TBB_LIB_PATH}" CACHE PATH "Full path of TBB library directory")
|
||||
link_directories("${TBB_LIB_DIR}")
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
if(NOT WITH_VTK OR ANDROID OR IOS)
|
||||
if(NOT WITH_VTK)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# VTK 6.x components
|
||||
find_package(VTK QUIET COMPONENTS vtkRenderingOpenGL vtkInteractionStyle vtkRenderingLOD vtkIOPLY vtkFiltersTexture vtkRenderingFreeType vtkIOExport NO_MODULE)
|
||||
find_package(VTK QUIET COMPONENTS vtkInteractionStyle vtkRenderingLOD vtkIOPLY vtkFiltersTexture vtkRenderingFreeType vtkIOExport NO_MODULE)
|
||||
IF(VTK_FOUND)
|
||||
IF(VTK_RENDERING_BACKEND) #in vtk 7, the rendering backend is exported as a var.
|
||||
find_package(VTK QUIET COMPONENTS vtkRendering${VTK_RENDERING_BACKEND} vtkInteractionStyle vtkRenderingLOD vtkIOPLY vtkFiltersTexture vtkRenderingFreeType vtkIOExport NO_MODULE)
|
||||
ELSE(VTK_RENDERING_BACKEND)
|
||||
find_package(VTK QUIET COMPONENTS vtkRenderingOpenGL vtkInteractionStyle vtkRenderingLOD vtkIOPLY vtkFiltersTexture vtkRenderingFreeType vtkIOExport NO_MODULE)
|
||||
ENDIF(VTK_RENDERING_BACKEND)
|
||||
ENDIF(VTK_FOUND)
|
||||
|
||||
# VTK 5.x components
|
||||
if(NOT VTK_FOUND)
|
||||
|
||||
@@ -594,7 +594,6 @@ macro(ocv_create_module)
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}
|
||||
LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}
|
||||
RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}
|
||||
INSTALL_NAME_DIR lib
|
||||
)
|
||||
|
||||
# For dynamic link numbering convenions
|
||||
|
||||
@@ -169,9 +169,9 @@ MACRO(_PCH_GET_TARGET_COMPILE_FLAGS _cflags _header_name _pch_path _dowarn )
|
||||
# if you have different versions of the headers for different build types
|
||||
# you may set _pch_dowarn
|
||||
IF (_dowarn)
|
||||
SET(${_cflags} "${PCH_ADDITIONAL_COMPILER_FLAGS} -include \"${CMAKE_CURRENT_BINARY_DIR}/${_header_name}\" -Winvalid-pch " )
|
||||
SET(${_cflags} "${PCH_ADDITIONAL_COMPILER_FLAGS} -Winvalid-pch " )
|
||||
ELSE (_dowarn)
|
||||
SET(${_cflags} "${PCH_ADDITIONAL_COMPILER_FLAGS} -include \"${CMAKE_CURRENT_BINARY_DIR}/${_header_name}\" " )
|
||||
SET(${_cflags} "${PCH_ADDITIONAL_COMPILER_FLAGS} " )
|
||||
ENDIF (_dowarn)
|
||||
|
||||
ELSE(CMAKE_COMPILER_IS_GNUCXX)
|
||||
|
||||
@@ -19,6 +19,9 @@ OpenCV makes it easy for businesses to utilize and modify the code.")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "${OPENCV_VERSION_MINOR}")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "${OPENCV_VERSION_PATCH}")
|
||||
set(CPACK_PACKAGE_VERSION "${OPENCV_VCSVERSION}")
|
||||
if (NOT "${OPENCV_VCSVERSION}" MATCHES "^${OPENCV_VERSION}.*")
|
||||
message(WARNING "CPACK_PACKAGE_VERSION does not match version provided by version.hpp header!")
|
||||
endif()
|
||||
set(OPENCV_DEBIAN_COPYRIGHT_FILE "")
|
||||
endif(NOT OPENCV_CUSTOM_PACKAGE_INFO)
|
||||
|
||||
@@ -86,7 +89,7 @@ set(CPACK_COMPONENT_PYTHON_DEPENDS libs)
|
||||
set(CPACK_DEB_PYTHON_PACKAGE_DEPENDS "python-numpy (>=${PYTHON_NUMPY_VERSION}), python${PYTHON_VERSION_MAJOR_MINOR}")
|
||||
set(CPACK_COMPONENT_TESTS_DEPENDS libs)
|
||||
if (HAVE_opencv_python)
|
||||
set(CPACK_DEB_TESTS_PACKAGE_DEPENDS "python-numpy (>=${PYTHON_NUMPY_VERSION}), python${PYTHON_VERSION_MAJOR_MINOR}, python-py | python-pytest")
|
||||
set(CPACK_DEB_TESTS_PACKAGE_DEPENDS "python-numpy (>=${PYTHON_NUMPY_VERSION}), python${PYTHON_VERSION_MAJOR_MINOR}")
|
||||
endif()
|
||||
|
||||
if(HAVE_CUDA)
|
||||
@@ -227,6 +230,32 @@ function(ocv_generate_lintian_overrides_file comp)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(ocv_get_lintian_version version)
|
||||
find_program(LINTIAN_EXECUTABLE lintian)
|
||||
|
||||
if(NOT LINTIAN_EXECUTABLE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND ${LINTIAN_EXECUTABLE} --version
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
RESULT_VARIABLE LINTIAN_EXITCODE
|
||||
OUTPUT_VARIABLE LINTIAN_VERSION
|
||||
ERROR_QUIET)
|
||||
|
||||
if(NOT LINTIAN_EXITCODE EQUAL 0)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(LINTIAN_VERSION MATCHES "([0-9]+\\.[0-9]+\\.[0-9]+)")
|
||||
set(LINTIAN_VERSION "${CMAKE_MATCH_1}" CACHE INTERNAL "Lintian version")
|
||||
endif()
|
||||
|
||||
set("${version}" "${LINTIAN_VERSION}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
ocv_get_lintian_version(LINTIAN_VERSION)
|
||||
|
||||
set(LIBS_LINTIAN_OVERRIDES "binary-or-shlib-defines-rpath" # usr/lib/libopencv_core.so.2.4.12
|
||||
"package-name-doesnt-match-sonames") # libopencv-calib3d2.4 libopencv-contrib2.4
|
||||
|
||||
@@ -246,6 +275,11 @@ endif()
|
||||
set(DEV_LINTIAN_OVERRIDES "binary-or-shlib-defines-rpath" # usr/bin/opencv_traincascade
|
||||
"binary-without-manpage") # usr/bin/opencv_traincascade
|
||||
|
||||
if(LINTIAN_VERSION VERSION_GREATER "2.5.30" OR
|
||||
LINTIAN_VERSION VERSION_EQUAL "2.5.30")
|
||||
list(APPEND DEV_LINTIAN_OVERRIDES "pkg-config-bad-directive") # usr/lib/pkgconfig/opencv.pc -L/usr/local/cuda-7.0/lib64
|
||||
endif()
|
||||
|
||||
if(NOT INSTALL_C_EXAMPLES)
|
||||
set(SAMPLES_LINTIAN_OVERRIDES "empty-binary-package") # samples are not installed
|
||||
endif()
|
||||
@@ -258,6 +292,13 @@ else()
|
||||
set(TESTS_LINTIAN_OVERRIDES "empty-binary-package") # there is no tests
|
||||
endif()
|
||||
|
||||
set(ALL_COMPONENTS "libs" "dev" "docs" "python" "java" "samples" "tests")
|
||||
|
||||
foreach (comp ${ALL_COMPONENTS})
|
||||
string(TOUPPER ${comp} comp_upcase)
|
||||
list(APPEND ${comp_upcase}_LINTIAN_OVERRIDES "misplaced-extra-member-in-deb") # for signed packages
|
||||
endforeach()
|
||||
|
||||
if(CPACK_GENERATOR STREQUAL "DEB")
|
||||
find_program(GZIP_TOOL NAMES "gzip" PATHS "/bin" "/usr/bin" "/usr/local/bin")
|
||||
if(NOT GZIP_TOOL)
|
||||
@@ -269,7 +310,6 @@ if(CPACK_GENERATOR STREQUAL "DEB")
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
set(CHANGELOG_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}")
|
||||
set(ALL_COMPONENTS "libs" "dev" "docs" "python" "java" "samples" "tests")
|
||||
foreach (comp ${ALL_COMPONENTS})
|
||||
string(TOUPPER "${comp}" comp_upcase)
|
||||
|
||||
|
||||
@@ -109,6 +109,9 @@
|
||||
/* NVidia Video Decoding API*/
|
||||
#cmakedefine HAVE_NVCUVID
|
||||
|
||||
/* NVidia Video Encoding API*/
|
||||
#cmakedefine HAVE_NVCUVENC
|
||||
|
||||
/* OpenCL Support */
|
||||
#cmakedefine HAVE_OPENCL
|
||||
#cmakedefine HAVE_OPENCL_STATIC
|
||||
|
||||
@@ -107,7 +107,7 @@ for t in $OPENCV_PYTHON_TESTS;
|
||||
do
|
||||
test_name=`basename "$t"`
|
||||
|
||||
cmd="py.test --junitxml $test_name.xml \"$OPENCV_TEST_PATH\"/$t"
|
||||
cmd="python \"$OPENCV_TEST_PATH\"/$t -v"
|
||||
|
||||
seg_reg="s/^/${TEXT_CYAN}[$test_name]${TEXT_RESET} /" # append test name
|
||||
|
||||
|
||||
@@ -18,5 +18,37 @@ if(INSTALL_TESTS AND OPENCV_TEST_DATA_PATH)
|
||||
DIRECTORY_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE
|
||||
GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
|
||||
DESTINATION share/OpenCV/testdata COMPONENT tests)
|
||||
if(BUILD_opencv_python)
|
||||
file(GLOB DATAFILES_CPP ../samples/cpp/left*.jpg)
|
||||
list(APPEND DATAFILES_CPP
|
||||
"../samples/cpp/board.jpg"
|
||||
"../samples/cpp/pic1.png"
|
||||
"../samples/cpp/pic6.png"
|
||||
"../samples/cpp/right01.jpg"
|
||||
"../samples/cpp/right02.jpg"
|
||||
"../samples/cpp/building.jpg"
|
||||
"../samples/cpp/tsukuba_l.png"
|
||||
"../samples/cpp/tsukuba_r.png"
|
||||
"../samples/cpp/letter-recognition.data")
|
||||
install(FILES ${DATAFILES_CPP} DESTINATION share/OpenCV/testdata/samples/cpp COMPONENT tests)
|
||||
set(DATAFILES_C
|
||||
"../samples/c/lena.jpg"
|
||||
"../samples/c/box.png")
|
||||
install(FILES ${DATAFILES_C} DESTINATION share/OpenCV/testdata/samples/c COMPONENT tests)
|
||||
set(DATAFILES_GPU
|
||||
"../samples/gpu/basketball1.png"
|
||||
"../samples/gpu/basketball2.png"
|
||||
"../samples/gpu/rubberwhale1.png")
|
||||
install(FILES ${DATAFILES_GPU} DESTINATION share/OpenCV/testdata/samples/gpu COMPONENT tests)
|
||||
set(DATAFILES_PYTHON
|
||||
"../samples/python2/data/graf1.png"
|
||||
"../samples/python2/data/pca_test1.jpg"
|
||||
"../samples/python2/data/digits.png")
|
||||
install(FILES ${DATAFILES_PYTHON} DESTINATION share/OpenCV/testdata/samples/python2/data COMPONENT tests)
|
||||
set(DATAFILES_CASCADES
|
||||
"haarcascades/haarcascade_frontalface_alt.xml"
|
||||
"haarcascades/haarcascade_eye.xml")
|
||||
install(FILES ${DATAFILES_CASCADES} DESTINATION share/OpenCV/testdata/data/haarcascades COMPONENT tests)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@@ -43,19 +43,41 @@
|
||||
#ifndef __OPENCV_ALL_HPP__
|
||||
#define __OPENCV_ALL_HPP__
|
||||
|
||||
#include "opencv2/opencv_modules.hpp"
|
||||
|
||||
#include "opencv2/core/core_c.h"
|
||||
#include "opencv2/core/core.hpp"
|
||||
#ifdef HAVE_OPENCV_FLANN
|
||||
#include "opencv2/flann/miniflann.hpp"
|
||||
#endif
|
||||
#ifdef HAVE_OPENCV_IMGPROC
|
||||
#include "opencv2/imgproc/imgproc_c.h"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#endif
|
||||
#ifdef HAVE_OPENCV_PHOTO
|
||||
#include "opencv2/photo/photo.hpp"
|
||||
#endif
|
||||
#ifdef HAVE_OPENCV_VIDEO
|
||||
#include "opencv2/video/video.hpp"
|
||||
#endif
|
||||
#ifdef HAVE_OPENCV_FEATURES2D
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
#endif
|
||||
#ifdef HAVE_OPENCV_OBJDETECT
|
||||
#include "opencv2/objdetect/objdetect.hpp"
|
||||
#endif
|
||||
#ifdef HAVE_OPENCV_CALIB3D
|
||||
#include "opencv2/calib3d/calib3d.hpp"
|
||||
#endif
|
||||
#ifdef HAVE_OPENCV_ML
|
||||
#include "opencv2/ml/ml.hpp"
|
||||
#endif
|
||||
#ifdef HAVE_OPENCV_HIGHGUI
|
||||
#include "opencv2/highgui/highgui_c.h"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#endif
|
||||
#ifdef HAVE_OPENCV_CONTRIB
|
||||
#include "opencv2/contrib/contrib.hpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -197,7 +197,7 @@ namespace cv
|
||||
}
|
||||
|
||||
resultsMutex.lock();
|
||||
if ( (localInliers.size() > inliers.size()) || (localInliers.size() == inliers.size() && curIndex > bestIndex))
|
||||
if ( (localInliers.size() > inliers.size()) || (localInliers.size() == inliers.size() && inliers.size() > 0 && curIndex > bestIndex))
|
||||
{
|
||||
inliers.clear();
|
||||
inliers.resize(localInliers.size());
|
||||
|
||||
@@ -344,7 +344,7 @@ static void findStereoCorrespondenceBM_SSE2( const Mat& left, const Mat& right,
|
||||
{
|
||||
hsad = hsad0 - dy0*ndisp; cbuf = cbuf0 + (x + wsz2 + 1)*cstep - dy0*ndisp;
|
||||
lptr = lptr0 + MIN(MAX(x, -lofs), width-lofs-1) - dy0*sstep;
|
||||
rptr = rptr0 + MIN(MAX(x, -rofs), width-rofs-1) - dy0*sstep;
|
||||
rptr = rptr0 + MIN(MAX(x, -rofs), width-rofs-ndisp) - dy0*sstep;
|
||||
|
||||
for( y = -dy0; y < height + dy1; y++, hsad += ndisp, cbuf += ndisp, lptr += sstep, rptr += sstep )
|
||||
{
|
||||
@@ -385,7 +385,7 @@ static void findStereoCorrespondenceBM_SSE2( const Mat& left, const Mat& right,
|
||||
hsad = hsad0 - dy0*ndisp;
|
||||
lptr_sub = lptr0 + MIN(MAX(x0, -lofs), width-1-lofs) - dy0*sstep;
|
||||
lptr = lptr0 + MIN(MAX(x1, -lofs), width-1-lofs) - dy0*sstep;
|
||||
rptr = rptr0 + MIN(MAX(x1, -rofs), width-1-rofs) - dy0*sstep;
|
||||
rptr = rptr0 + MIN(MAX(x1, -rofs), width-ndisp-rofs) - dy0*sstep;
|
||||
|
||||
for( y = -dy0; y < height + dy1; y++, cbuf += ndisp, cbuf_sub += ndisp,
|
||||
hsad += ndisp, lptr += sstep, lptr_sub += sstep, rptr += sstep )
|
||||
@@ -610,7 +610,7 @@ findStereoCorrespondenceBM( const Mat& left, const Mat& right,
|
||||
{
|
||||
hsad = hsad0 - dy0*ndisp; cbuf = cbuf0 + (x + wsz2 + 1)*cstep - dy0*ndisp;
|
||||
lptr = lptr0 + std::min(std::max(x, -lofs), width-lofs-1) - dy0*sstep;
|
||||
rptr = rptr0 + std::min(std::max(x, -rofs), width-rofs-1) - dy0*sstep;
|
||||
rptr = rptr0 + std::min(std::max(x, -rofs), width-rofs-ndisp) - dy0*sstep;
|
||||
|
||||
for( y = -dy0; y < height + dy1; y++, hsad += ndisp, cbuf += ndisp, lptr += sstep, rptr += sstep )
|
||||
{
|
||||
@@ -661,7 +661,7 @@ findStereoCorrespondenceBM( const Mat& left, const Mat& right,
|
||||
hsad = hsad0 - dy0*ndisp;
|
||||
lptr_sub = lptr0 + MIN(MAX(x0, -lofs), width-1-lofs) - dy0*sstep;
|
||||
lptr = lptr0 + MIN(MAX(x1, -lofs), width-1-lofs) - dy0*sstep;
|
||||
rptr = rptr0 + MIN(MAX(x1, -rofs), width-1-rofs) - dy0*sstep;
|
||||
rptr = rptr0 + MIN(MAX(x1, -rofs), width-ndisp-rofs) - dy0*sstep;
|
||||
|
||||
for( y = -dy0; y < height + dy1; y++, cbuf += ndisp, cbuf_sub += ndisp,
|
||||
hsad += ndisp, lptr += sstep, lptr_sub += sstep, rptr += sstep )
|
||||
|
||||
@@ -99,7 +99,7 @@ StereoSGBM::~StereoSGBM()
|
||||
}
|
||||
|
||||
/*
|
||||
For each pixel row1[x], max(-maxD, 0) <= minX <= x < maxX <= width - max(0, -minD),
|
||||
For each pixel row1[x], max(-maxD, 0) <= minX <= x < maxX <= width - max(0, minD),
|
||||
and for each disparity minD<=d<maxD the function
|
||||
computes the cost (cost[(x-minX)*(maxD - minD) + (d - minD)]), depending on the difference between
|
||||
row1[x] and row2[x-d]. The subpixel algorithm from
|
||||
@@ -114,8 +114,8 @@ static void calcPixelCostBT( const Mat& img1, const Mat& img2, int y,
|
||||
int tabOfs, int )
|
||||
{
|
||||
int x, c, width = img1.cols, cn = img1.channels();
|
||||
int minX1 = max(-maxD, 0), maxX1 = width + min(minD, 0);
|
||||
int minX2 = max(minX1 - maxD, 0), maxX2 = min(maxX1 - minD, width);
|
||||
int minX1 = max(-maxD, 0), maxX1 = width + min(-minD, 0);
|
||||
int minX2 = max(minX1 + minD, 0), maxX2 = min(maxX1 + maxD, width);
|
||||
int D = maxD - minD, width1 = maxX1 - minX1, width2 = maxX2 - minX2;
|
||||
const PixType *row1 = img1.ptr<PixType>(y), *row2 = img2.ptr<PixType>(y);
|
||||
PixType *prow1 = buffer + width2*2, *prow2 = prow1 + width*cn*2;
|
||||
@@ -200,6 +200,19 @@ static void calcPixelCostBT( const Mat& img1, const Mat& img2, int y,
|
||||
int u0 = min(ul, ur); u0 = min(u0, u);
|
||||
int u1 = max(ul, ur); u1 = max(u1, u);
|
||||
|
||||
int minDlocal = max(minD, x-width+1);
|
||||
int maxDlocal = min(maxD, x);
|
||||
int d;
|
||||
for( d = minD; d < minDlocal; d++ )
|
||||
{
|
||||
int v = prow2[0];
|
||||
int v0 = buffer[0];
|
||||
int v1 = buffer[width2];
|
||||
int c0 = max(0, u - v1); c0 = max(c0, v0 - u);
|
||||
int c1 = max(0, v - u1); c1 = max(c1, u0 - v);
|
||||
|
||||
cost[x*D + d] = (CostType)(cost[x*D+d] + (min(c0, c1) >> diff_scale));
|
||||
}
|
||||
#if CV_SSE2
|
||||
if( useSIMD )
|
||||
{
|
||||
@@ -207,7 +220,7 @@ static void calcPixelCostBT( const Mat& img1, const Mat& img2, int y,
|
||||
__m128i _u1 = _mm_set1_epi8((char)u1), z = _mm_setzero_si128();
|
||||
__m128i ds = _mm_cvtsi32_si128(diff_scale);
|
||||
|
||||
for( int d = minD; d < maxD; d += 16 )
|
||||
for( ; d < maxDlocal - 15; d += 16 )
|
||||
{
|
||||
__m128i _v = _mm_loadu_si128((const __m128i*)(prow2 + width-x-1 + d));
|
||||
__m128i _v0 = _mm_loadu_si128((const __m128i*)(buffer + width-x-1 + d));
|
||||
@@ -223,19 +236,26 @@ static void calcPixelCostBT( const Mat& img1, const Mat& img2, int y,
|
||||
_mm_store_si128((__m128i*)(cost + x*D + d + 8), _mm_adds_epi16(c1, _mm_srl_epi16(_mm_unpackhi_epi8(diff,z), ds)));
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
for( ; d < maxDlocal; d++ )
|
||||
{
|
||||
for( int d = minD; d < maxD; d++ )
|
||||
{
|
||||
int v = prow2[width-x-1 + d];
|
||||
int v0 = buffer[width-x-1 + d];
|
||||
int v1 = buffer[width-x-1 + d + width2];
|
||||
int c0 = max(0, u - v1); c0 = max(c0, v0 - u);
|
||||
int c1 = max(0, v - u1); c1 = max(c1, u0 - v);
|
||||
int v = prow2[width-x-1 + d];
|
||||
int v0 = buffer[width-x-1 + d];
|
||||
int v1 = buffer[width-x-1 + d + width2];
|
||||
int c0 = max(0, u - v1); c0 = max(c0, v0 - u);
|
||||
int c1 = max(0, v - u1); c1 = max(c1, u0 - v);
|
||||
|
||||
cost[x*D + d] = (CostType)(cost[x*D+d] + (min(c0, c1) >> diff_scale));
|
||||
}
|
||||
cost[x*D + d] = (CostType)(cost[x*D+d] + (min(c0, c1) >> diff_scale));
|
||||
}
|
||||
for( ; d < maxD; d++ )
|
||||
{
|
||||
int v = prow2[width-1];
|
||||
int v0 = buffer[width-1];
|
||||
int v1 = buffer[width-1 + width2];
|
||||
int c0 = max(0, u - v1); c0 = max(c0, v0 - u);
|
||||
int c1 = max(0, v - u1); c1 = max(c1, u0 - v);
|
||||
|
||||
cost[x*D + d] = (CostType)(cost[x*D+d] + (min(c0, c1) >> diff_scale));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -329,7 +349,7 @@ static void computeDisparitySGBM( const Mat& img1, const Mat& img2,
|
||||
int disp12MaxDiff = params.disp12MaxDiff > 0 ? params.disp12MaxDiff : 1;
|
||||
int P1 = params.P1 > 0 ? params.P1 : 2, P2 = max(params.P2 > 0 ? params.P2 : 5, P1+1);
|
||||
int k, width = disp1.cols, height = disp1.rows;
|
||||
int minX1 = max(-maxD, 0), maxX1 = width + min(minD, 0);
|
||||
int minX1 = max(-maxD, 0), maxX1 = width + min(-minD, 0);
|
||||
int D = maxD - minD, width1 = maxX1 - minX1;
|
||||
int INVALID_DISP = minD - 1, INVALID_DISP_SCALED = INVALID_DISP*DISP_SCALE;
|
||||
int SW2 = SADWindowSize.width/2, SH2 = SADWindowSize.height/2;
|
||||
@@ -377,6 +397,7 @@ static void computeDisparitySGBM( const Mat& img1, const Mat& img2,
|
||||
|
||||
// summary cost over different (nDirs) directions
|
||||
CostType* Cbuf = (CostType*)alignPtr(buffer.data, ALIGN);
|
||||
memset(Cbuf, 0, CSBufSize*sizeof(CostType));
|
||||
CostType* Sbuf = Cbuf + CSBufSize;
|
||||
CostType* hsumBuf = Sbuf + CSBufSize;
|
||||
CostType* pixDiff = hsumBuf + costBufSize*hsumBufNRows;
|
||||
|
||||
@@ -2593,6 +2593,9 @@ CV_EXPORTS_W double kmeans( InputArray data, int K, CV_OUT InputOutputArray best
|
||||
//! returns the thread-local Random number generator
|
||||
CV_EXPORTS RNG& theRNG();
|
||||
|
||||
//! sets state of the thread-local Random number generator
|
||||
CV_EXPORTS_W void setRNGSeed(int seed);
|
||||
|
||||
//! returns the next unifomly-distributed random number of the specified type
|
||||
template<typename _Tp> static inline _Tp randu() { return (_Tp)theRNG(); }
|
||||
|
||||
|
||||
@@ -821,6 +821,9 @@ template<typename _Tp> inline Mat_<_Tp>::Mat_(int _dims, const int* _sz)
|
||||
template<typename _Tp> inline Mat_<_Tp>::Mat_(int _dims, const int* _sz, const _Tp& _s)
|
||||
: Mat(_dims, _sz, DataType<_Tp>::type, Scalar(_s)) {}
|
||||
|
||||
template<typename _Tp> inline Mat_<_Tp>::Mat_(int _dims, const int* _sz, _Tp* _data, const size_t* _steps)
|
||||
: Mat(_dims, _sz, DataType<_Tp>::type, _data, _steps) {}
|
||||
|
||||
template<typename _Tp> inline Mat_<_Tp>::Mat_(const Mat_<_Tp>& m, const Range* ranges)
|
||||
: Mat(m, ranges) {}
|
||||
|
||||
|
||||
@@ -305,6 +305,31 @@ enum {
|
||||
#define CV_CMP(a,b) (((a) > (b)) - ((a) < (b)))
|
||||
#define CV_SIGN(a) CV_CMP((a),0)
|
||||
|
||||
#if defined __GNUC__ && defined __arm__ && (defined __ARM_PCS_VFP || defined __ARM_VFPV3__)
|
||||
# define CV_VFP 1
|
||||
#else
|
||||
# define CV_VFP 0
|
||||
#endif
|
||||
|
||||
|
||||
#if CV_VFP
|
||||
// 1. general scheme
|
||||
#define ARM_ROUND(_value, _asm_string) \
|
||||
int res; \
|
||||
float temp; \
|
||||
(void)temp; \
|
||||
asm(_asm_string : [res] "=r" (res), [temp] "=w" (temp) : [value] "w" (_value)); \
|
||||
return res;
|
||||
// 2. version for double
|
||||
#ifdef __clang__
|
||||
#define ARM_ROUND_DBL(value) ARM_ROUND(value, "vcvtr.s32.f64 %[temp], %[value] \n vmov %[res], %[temp]")
|
||||
#else
|
||||
#define ARM_ROUND_DBL(value) ARM_ROUND(value, "vcvtr.s32.f64 %[temp], %P[value] \n vmov %[res], %[temp]")
|
||||
#endif
|
||||
// 3. version for float
|
||||
#define ARM_ROUND_FLT(value) ARM_ROUND(value, "vcvtr.s32.f32 %[temp], %[value]\n vmov %[res], %[temp]")
|
||||
#endif // CV_VFP
|
||||
|
||||
CV_INLINE int cvRound( double value )
|
||||
{
|
||||
#if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__ && defined __SSE2__ && !defined __APPLE__)
|
||||
@@ -323,6 +348,8 @@ CV_INLINE int cvRound( double value )
|
||||
#elif defined CV_ICC || defined __GNUC__
|
||||
# ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
TEGRA_ROUND(value);
|
||||
# elif CV_VFP
|
||||
ARM_ROUND_DBL(value)
|
||||
# else
|
||||
return (int)lrint(value);
|
||||
# endif
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
#define CV_VERSION_EPOCH 2
|
||||
#define CV_VERSION_MAJOR 4
|
||||
#define CV_VERSION_MINOR 12
|
||||
#define CV_VERSION_MINOR 13
|
||||
#define CV_VERSION_REVISION 0
|
||||
|
||||
#define CVAUX_STR_EXP(__A) #__A
|
||||
|
||||
@@ -3439,7 +3439,7 @@ ptrdiff_t operator - (const MatConstIterator& b, const MatConstIterator& a)
|
||||
if( a.m != b.m )
|
||||
return INT_MAX;
|
||||
if( a.sliceEnd == b.sliceEnd )
|
||||
return (b.ptr - a.ptr)/b.elemSize;
|
||||
return (b.ptr - a.ptr)/static_cast<ptrdiff_t>(b.elemSize);
|
||||
|
||||
return b.lpos() - a.lpos();
|
||||
}
|
||||
|
||||
@@ -5248,7 +5248,7 @@ FileStorage& operator << (FileStorage& fs, const string& str)
|
||||
}
|
||||
else if( fs.state == NAME_EXPECTED + INSIDE_MAP )
|
||||
{
|
||||
if( !cv_isalpha(*_str) )
|
||||
if (!cv_isalpha(*_str) && *_str != '_')
|
||||
CV_Error_( CV_StsError, ("Incorrect element name %s", _str) );
|
||||
fs.elname = str;
|
||||
fs.state = VALUE_EXPECTED + INSIDE_MAP;
|
||||
|
||||
@@ -806,6 +806,11 @@ RNG& theRNG()
|
||||
|
||||
}
|
||||
|
||||
void cv::setRNGSeed(int seed)
|
||||
{
|
||||
theRNG() = RNG(static_cast<uint64>(seed));
|
||||
}
|
||||
|
||||
void cv::randu(InputOutputArray dst, InputArray low, InputArray high)
|
||||
{
|
||||
theRNG().fill(dst, RNG::UNIFORM, low, high);
|
||||
|
||||
@@ -522,3 +522,14 @@ TEST(Core_InputOutput, FileStorage)
|
||||
sprintf(arr, "sprintf is hell %d", 666);
|
||||
EXPECT_NO_THROW(f << arr);
|
||||
}
|
||||
|
||||
TEST(Core_InputOutput, FileStorageKey)
|
||||
{
|
||||
cv::FileStorage f("dummy.yml", cv::FileStorage::WRITE | cv::FileStorage::MEMORY);
|
||||
|
||||
EXPECT_NO_THROW(f << "key1" << "value1");
|
||||
EXPECT_NO_THROW(f << "_key2" << "value2");
|
||||
EXPECT_NO_THROW(f << "key_3" << "value3");
|
||||
const std::string expected = "%YAML:1.0\nkey1: value1\n_key2: value2\nkey_3: value3\n";
|
||||
ASSERT_STREQ(f.releaseAndGetString().c_str(), expected.c_str());
|
||||
}
|
||||
|
||||
@@ -52,13 +52,46 @@ Maximally stable extremal region extractor. ::
|
||||
void operator()( const Mat& image, vector<vector<Point> >& msers, const Mat& mask ) const;
|
||||
};
|
||||
|
||||
The class encapsulates all the parameters of the MSER extraction algorithm (see
|
||||
http://en.wikipedia.org/wiki/Maximally_stable_extremal_regions). Also see http://code.opencv.org/projects/opencv/wiki/MSER for useful comments and parameters description.
|
||||
The class encapsulates all the parameters of the MSER extraction algorithm (see [wiki]_ article).
|
||||
|
||||
.. note::
|
||||
|
||||
* (Python) A complete example showing the use of the MSER detector can be found at opencv_source_code/samples/python2/mser.py
|
||||
* there are two different implementation of MSER: one for grey image, one for color image the grey image algorithm is taken from: [nister2008linear]_ ; the paper claims to be faster than union-find method; it actually get 1.5~2m/s on my centrino L7200 1.2GHz laptop.
|
||||
|
||||
* the color image algorithm is taken from: [forssen2007maximally]_ ; it should be much slower than grey image method ( 3~4 times ); the chi_table.h file is taken directly from paper's source code which is distributed under GPL.
|
||||
|
||||
* (Python) A complete example showing the use of the MSER detector can be found at opencv_source_code/samples/python2/mser.py
|
||||
|
||||
.. [wiki] http://en.wikipedia.org/wiki/Maximally_stable_extremal_regions
|
||||
.. [nister2008linear] David Nistér and Henrik Stewénius. Linear time maximally stable extremal regions. In Computer Vision–ECCV 2008, pages 183–196. Springer, 2008.
|
||||
.. [forssen2007maximally] Per-Erik Forssén. Maximally stable colour regions for recognition and matching. In Computer Vision and Pattern Recognition, 2007. CVPR'07. IEEE Conference on, pages 1–8. IEEE, 2007.
|
||||
|
||||
MSER::MSER
|
||||
----------
|
||||
The MSER constructor
|
||||
|
||||
.. ocv:function:: MSER::MSER(int _delta=5, int _min_area=60, int _max_area=14400, double _max_variation=0.25, double _min_diversity=.2, int _max_evolution=200, double _area_threshold=1.01, double _min_margin=0.003, int _edge_blur_size=5)
|
||||
|
||||
:param _delta: Compares (sizei - sizei-delta)/sizei-delta
|
||||
:param _min_area: Prune the area which smaller than minArea
|
||||
:param _max_area: Prune the area which bigger than maxArea
|
||||
:param _max_variation: Prune the area have simliar size to its children
|
||||
:param _min_diversity: For color image, trace back to cut off mser with diversity less than min_diversity
|
||||
:param _max_evolution: For color image, the evolution steps
|
||||
:param _area_threshold: For color image, the area threshold to cause re-initialize
|
||||
:param _min_margin: For color image, ignore too small margin
|
||||
:param _edge_blur_size: For color image, the aperture size for edge blur
|
||||
|
||||
MSER::operator()
|
||||
----------------
|
||||
|
||||
Detect MSER regions
|
||||
|
||||
.. ocv:function:: void MSER::operator()(const Mat& image, vector<vector<Point> >& msers, const Mat& mask=Mat() ) const
|
||||
|
||||
:param image: Input image (8UC1, 8UC3 or 8UC4)
|
||||
:param msers: Resulting list of point sets
|
||||
:param mask: The operation mask
|
||||
|
||||
ORB
|
||||
---
|
||||
|
||||
@@ -54,11 +54,14 @@ if(HAVE_CUDA)
|
||||
endif()
|
||||
|
||||
if(WITH_NVCUVID)
|
||||
set(cuda_link_libs ${cuda_link_libs} ${CUDA_CUDA_LIBRARY} ${CUDA_nvcuvid_LIBRARY})
|
||||
if(HAVE_NVCUVID)
|
||||
set(cuda_link_libs ${cuda_link_libs} ${CUDA_CUDA_LIBRARY} ${CUDA_nvcuvid_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
find_cuda_helper_libs(nvcuvenc)
|
||||
set(cuda_link_libs ${cuda_link_libs} ${CUDA_nvcuvenc_LIBRARY})
|
||||
if(HAVE_NVCUVENC)
|
||||
set(cuda_link_libs ${cuda_link_libs} ${CUDA_nvcuvenc_LIBRARY})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_FFMPEG)
|
||||
|
||||
@@ -98,7 +98,9 @@
|
||||
#include <nvcuvid.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <NVEncoderAPI.h>
|
||||
#ifdef HAVE_NVCUVENC
|
||||
#include <NVEncoderAPI.h>
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#if !defined(HAVE_CUDA) || defined(CUDA_DISABLER) || !defined(HAVE_NVCUVID) || !defined(WIN32)
|
||||
#if !defined(HAVE_CUDA) || defined(CUDA_DISABLER) || !defined(HAVE_NVCUVENC) || !defined(WIN32)
|
||||
|
||||
class cv::gpu::VideoWriter_GPU::Impl
|
||||
{
|
||||
|
||||
@@ -118,11 +118,6 @@ extern "C" {
|
||||
#define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
|
||||
#endif
|
||||
|
||||
/* PIX_FMT_RGBA32 macro changed in newer ffmpeg versions */
|
||||
#ifndef PIX_FMT_RGBA32
|
||||
#define PIX_FMT_RGBA32 PIX_FMT_RGB32
|
||||
#endif
|
||||
|
||||
#define CALC_FFMPEG_VERSION(a,b,c) ( a<<16 | b<<8 | c )
|
||||
|
||||
#if defined WIN32 || defined _WIN32
|
||||
@@ -132,6 +127,11 @@ extern "C" {
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/time.h>
|
||||
#if defined __APPLE__
|
||||
#include <mach/clock.h>
|
||||
#include <mach/mach.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
@@ -156,6 +156,156 @@ extern "C" {
|
||||
# define CV_CODEC(name) name
|
||||
#endif
|
||||
|
||||
#if LIBAVUTIL_BUILD < (LIBAVUTIL_VERSION_MICRO >= 100 \
|
||||
? CALC_FFMPEG_VERSION(51, 74, 100) : CALC_FFMPEG_VERSION(51, 42, 0))
|
||||
#define AVPixelFormat PixelFormat
|
||||
#define AV_PIX_FMT_BGR24 PIX_FMT_BGR24
|
||||
#define AV_PIX_FMT_RGB24 PIX_FMT_RGB24
|
||||
#define AV_PIX_FMT_GRAY8 PIX_FMT_GRAY8
|
||||
#define AV_PIX_FMT_YUV422P PIX_FMT_YUV422P
|
||||
#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
|
||||
#define AV_PIX_FMT_YUV444P PIX_FMT_YUV444P
|
||||
#define AV_PIX_FMT_YUVJ420P PIX_FMT_YUVJ420P
|
||||
#define AV_PIX_FMT_GRAY16LE PIX_FMT_GRAY16LE
|
||||
#define AV_PIX_FMT_GRAY16BE PIX_FMT_GRAY16BE
|
||||
#endif
|
||||
|
||||
#if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 \
|
||||
? CALC_FFMPEG_VERSION(52, 38, 100) : CALC_FFMPEG_VERSION(52, 13, 0))
|
||||
#define USE_AV_FRAME_GET_BUFFER 1
|
||||
#else
|
||||
#define USE_AV_FRAME_GET_BUFFER 0
|
||||
#ifndef AV_NUM_DATA_POINTERS // required for 0.7.x/0.8.x ffmpeg releases
|
||||
#define AV_NUM_DATA_POINTERS 4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef USE_AV_INTERRUPT_CALLBACK
|
||||
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 21, 0)
|
||||
#define USE_AV_INTERRUPT_CALLBACK 1
|
||||
#else
|
||||
#define USE_AV_INTERRUPT_CALLBACK 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if USE_AV_INTERRUPT_CALLBACK
|
||||
#define LIBAVFORMAT_INTERRUPT_OPEN_TIMEOUT_MS 30000
|
||||
#define LIBAVFORMAT_INTERRUPT_READ_TIMEOUT_MS 30000
|
||||
|
||||
#ifdef WIN32
|
||||
// http://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows
|
||||
|
||||
static
|
||||
inline LARGE_INTEGER get_filetime_offset()
|
||||
{
|
||||
SYSTEMTIME s;
|
||||
FILETIME f;
|
||||
LARGE_INTEGER t;
|
||||
|
||||
s.wYear = 1970;
|
||||
s.wMonth = 1;
|
||||
s.wDay = 1;
|
||||
s.wHour = 0;
|
||||
s.wMinute = 0;
|
||||
s.wSecond = 0;
|
||||
s.wMilliseconds = 0;
|
||||
SystemTimeToFileTime(&s, &f);
|
||||
t.QuadPart = f.dwHighDateTime;
|
||||
t.QuadPart <<= 32;
|
||||
t.QuadPart |= f.dwLowDateTime;
|
||||
return t;
|
||||
}
|
||||
|
||||
static
|
||||
inline void get_monotonic_time(timespec *tv)
|
||||
{
|
||||
LARGE_INTEGER t;
|
||||
FILETIME f;
|
||||
double microseconds;
|
||||
static LARGE_INTEGER offset;
|
||||
static double frequencyToMicroseconds;
|
||||
static int initialized = 0;
|
||||
static BOOL usePerformanceCounter = 0;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
LARGE_INTEGER performanceFrequency;
|
||||
initialized = 1;
|
||||
usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency);
|
||||
if (usePerformanceCounter)
|
||||
{
|
||||
QueryPerformanceCounter(&offset);
|
||||
frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = get_filetime_offset();
|
||||
frequencyToMicroseconds = 10.;
|
||||
}
|
||||
}
|
||||
|
||||
if (usePerformanceCounter)
|
||||
{
|
||||
QueryPerformanceCounter(&t);
|
||||
} else {
|
||||
GetSystemTimeAsFileTime(&f);
|
||||
t.QuadPart = f.dwHighDateTime;
|
||||
t.QuadPart <<= 32;
|
||||
t.QuadPart |= f.dwLowDateTime;
|
||||
}
|
||||
|
||||
t.QuadPart -= offset.QuadPart;
|
||||
microseconds = (double)t.QuadPart / frequencyToMicroseconds;
|
||||
t.QuadPart = microseconds;
|
||||
tv->tv_sec = t.QuadPart / 1000000;
|
||||
tv->tv_nsec = (t.QuadPart % 1000000) * 1000;
|
||||
}
|
||||
#else
|
||||
static
|
||||
inline void get_monotonic_time(timespec *time)
|
||||
{
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
clock_serv_t cclock;
|
||||
mach_timespec_t mts;
|
||||
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
|
||||
clock_get_time(cclock, &mts);
|
||||
mach_port_deallocate(mach_task_self(), cclock);
|
||||
time->tv_sec = mts.tv_sec;
|
||||
time->tv_nsec = mts.tv_nsec;
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, time);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
inline timespec get_monotonic_time_diff(timespec start, timespec end)
|
||||
{
|
||||
timespec temp;
|
||||
if (end.tv_nsec - start.tv_nsec < 0)
|
||||
{
|
||||
temp.tv_sec = end.tv_sec - start.tv_sec - 1;
|
||||
temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp.tv_sec = end.tv_sec - start.tv_sec;
|
||||
temp.tv_nsec = end.tv_nsec - start.tv_nsec;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
static
|
||||
inline double get_monotonic_time_diff_ms(timespec time1, timespec time2)
|
||||
{
|
||||
timespec delta = get_monotonic_time_diff(time1, time2);
|
||||
double milliseconds = delta.tv_sec * 1000 + (double)delta.tv_nsec / 1000000.0;
|
||||
|
||||
return milliseconds;
|
||||
}
|
||||
#endif // USE_AV_INTERRUPT_CALLBACK
|
||||
|
||||
static int get_number_of_cpus(void)
|
||||
{
|
||||
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(52, 111, 0)
|
||||
@@ -205,12 +355,41 @@ struct Image_FFMPEG
|
||||
};
|
||||
|
||||
|
||||
#if USE_AV_INTERRUPT_CALLBACK
|
||||
struct AVInterruptCallbackMetadata
|
||||
{
|
||||
timespec value;
|
||||
unsigned int timeout_after_ms;
|
||||
int timeout;
|
||||
};
|
||||
|
||||
static
|
||||
inline void _opencv_ffmpeg_free(void** ptr)
|
||||
{
|
||||
if(*ptr) free(*ptr);
|
||||
*ptr = 0;
|
||||
}
|
||||
|
||||
static
|
||||
inline int _opencv_ffmpeg_interrupt_callback(void *ptr)
|
||||
{
|
||||
AVInterruptCallbackMetadata* metadata = (AVInterruptCallbackMetadata*)ptr;
|
||||
assert(metadata);
|
||||
|
||||
if (metadata->timeout_after_ms == 0)
|
||||
{
|
||||
return 0; // timeout is disabled
|
||||
}
|
||||
|
||||
timespec now;
|
||||
get_monotonic_time(&now);
|
||||
|
||||
metadata->timeout = get_monotonic_time_diff_ms(metadata->value, now) > metadata->timeout_after_ms;
|
||||
|
||||
return metadata->timeout ? -1 : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
struct CvCapture_FFMPEG
|
||||
{
|
||||
@@ -264,6 +443,10 @@ struct CvCapture_FFMPEG
|
||||
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)
|
||||
AVDictionary *dict;
|
||||
#endif
|
||||
|
||||
#if USE_AV_INTERRUPT_CALLBACK
|
||||
AVInterruptCallbackMetadata interrupt_metadata;
|
||||
#endif
|
||||
};
|
||||
|
||||
void CvCapture_FFMPEG::init()
|
||||
@@ -301,8 +484,10 @@ void CvCapture_FFMPEG::close()
|
||||
|
||||
if( picture )
|
||||
{
|
||||
// FFmpeg and Libav added avcodec_free_frame in different versions.
|
||||
#if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \
|
||||
? CALC_FFMPEG_VERSION(55, 45, 101) : CALC_FFMPEG_VERSION(55, 28, 1))
|
||||
av_frame_free(&picture);
|
||||
#elif LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \
|
||||
? CALC_FFMPEG_VERSION(54, 59, 100) : CALC_FFMPEG_VERSION(54, 28, 0))
|
||||
avcodec_free_frame(&picture);
|
||||
#else
|
||||
@@ -333,11 +518,15 @@ void CvCapture_FFMPEG::close()
|
||||
ic = NULL;
|
||||
}
|
||||
|
||||
#if USE_AV_FRAME_GET_BUFFER
|
||||
av_frame_unref(&rgb_picture);
|
||||
#else
|
||||
if( rgb_picture.data[0] )
|
||||
{
|
||||
free( rgb_picture.data[0] );
|
||||
rgb_picture.data[0] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// free last packet if exist
|
||||
if (packet.data) {
|
||||
@@ -556,6 +745,16 @@ bool CvCapture_FFMPEG::open( const char* _filename )
|
||||
|
||||
close();
|
||||
|
||||
#if USE_AV_INTERRUPT_CALLBACK
|
||||
/* interrupt callback */
|
||||
interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_OPEN_TIMEOUT_MS;
|
||||
get_monotonic_time(&interrupt_metadata.value);
|
||||
|
||||
ic = avformat_alloc_context();
|
||||
ic->interrupt_callback.callback = _opencv_ffmpeg_interrupt_callback;
|
||||
ic->interrupt_callback.opaque = &interrupt_metadata;
|
||||
#endif
|
||||
|
||||
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)
|
||||
av_dict_set(&dict, "rtsp_transport", "tcp", 0);
|
||||
int err = avformat_open_input(&ic, _filename, NULL, &dict);
|
||||
@@ -619,19 +818,18 @@ bool CvCapture_FFMPEG::open( const char* _filename )
|
||||
|
||||
video_stream = i;
|
||||
video_st = ic->streams[i];
|
||||
#if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \
|
||||
? CALC_FFMPEG_VERSION(55, 45, 101) : CALC_FFMPEG_VERSION(55, 28, 1))
|
||||
picture = av_frame_alloc();
|
||||
#else
|
||||
picture = avcodec_alloc_frame();
|
||||
|
||||
rgb_picture.data[0] = (uint8_t*)malloc(
|
||||
avpicture_get_size( PIX_FMT_BGR24,
|
||||
enc->width, enc->height ));
|
||||
avpicture_fill( (AVPicture*)&rgb_picture, rgb_picture.data[0],
|
||||
PIX_FMT_BGR24, enc->width, enc->height );
|
||||
#endif
|
||||
|
||||
frame.width = enc->width;
|
||||
frame.height = enc->height;
|
||||
frame.cn = 3;
|
||||
frame.step = rgb_picture.linesize[0];
|
||||
frame.data = rgb_picture.data[0];
|
||||
frame.step = 0;
|
||||
frame.data = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -640,6 +838,11 @@ bool CvCapture_FFMPEG::open( const char* _filename )
|
||||
|
||||
exit_func:
|
||||
|
||||
#if USE_AV_INTERRUPT_CALLBACK
|
||||
// deactivate interrupt callback
|
||||
interrupt_metadata.timeout_after_ms = 0;
|
||||
#endif
|
||||
|
||||
if( !valid )
|
||||
close();
|
||||
|
||||
@@ -661,13 +864,27 @@ bool CvCapture_FFMPEG::grabFrame()
|
||||
frame_number > ic->streams[video_stream]->nb_frames )
|
||||
return false;
|
||||
|
||||
av_free_packet (&packet);
|
||||
|
||||
picture_pts = AV_NOPTS_VALUE_;
|
||||
|
||||
#if USE_AV_INTERRUPT_CALLBACK
|
||||
// activate interrupt callback
|
||||
get_monotonic_time(&interrupt_metadata.value);
|
||||
interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_READ_TIMEOUT_MS;
|
||||
#endif
|
||||
|
||||
// get the next frame
|
||||
while (!valid)
|
||||
{
|
||||
av_free_packet (&packet);
|
||||
|
||||
#if USE_AV_INTERRUPT_CALLBACK
|
||||
if (interrupt_metadata.timeout)
|
||||
{
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
int ret = av_read_frame(ic, &packet);
|
||||
if (ret == AVERROR(EAGAIN)) continue;
|
||||
|
||||
@@ -710,13 +927,16 @@ bool CvCapture_FFMPEG::grabFrame()
|
||||
if (count_errs > max_number_of_attempts)
|
||||
break;
|
||||
}
|
||||
|
||||
av_free_packet (&packet);
|
||||
}
|
||||
|
||||
if( valid && first_frame_number < 0 )
|
||||
first_frame_number = dts_to_frame_number(picture_pts);
|
||||
|
||||
#if USE_AV_INTERRUPT_CALLBACK
|
||||
// deactivate interrupt callback
|
||||
interrupt_metadata.timeout_after_ms = 0;
|
||||
#endif
|
||||
|
||||
// return if we have a new picture or not
|
||||
return valid;
|
||||
}
|
||||
@@ -727,38 +947,59 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int*
|
||||
if( !video_st || !picture->data[0] )
|
||||
return false;
|
||||
|
||||
avpicture_fill((AVPicture*)&rgb_picture, rgb_picture.data[0], PIX_FMT_RGB24,
|
||||
video_st->codec->width, video_st->codec->height);
|
||||
|
||||
if( img_convert_ctx == NULL ||
|
||||
frame.width != video_st->codec->width ||
|
||||
frame.height != video_st->codec->height )
|
||||
frame.height != video_st->codec->height ||
|
||||
frame.data == NULL )
|
||||
{
|
||||
if( img_convert_ctx )
|
||||
sws_freeContext(img_convert_ctx);
|
||||
|
||||
frame.width = video_st->codec->width;
|
||||
frame.height = video_st->codec->height;
|
||||
// Some sws_scale optimizations have some assumptions about alignment of data/step/width/height
|
||||
// Also we use coded_width/height to workaround problem with legacy ffmpeg versions (like n0.8)
|
||||
int buffer_width = video_st->codec->coded_width, buffer_height = video_st->codec->coded_height;
|
||||
|
||||
img_convert_ctx = sws_getCachedContext(
|
||||
NULL,
|
||||
video_st->codec->width, video_st->codec->height,
|
||||
img_convert_ctx,
|
||||
buffer_width, buffer_height,
|
||||
video_st->codec->pix_fmt,
|
||||
video_st->codec->width, video_st->codec->height,
|
||||
PIX_FMT_BGR24,
|
||||
buffer_width, buffer_height,
|
||||
AV_PIX_FMT_BGR24,
|
||||
SWS_BICUBIC,
|
||||
NULL, NULL, NULL
|
||||
);
|
||||
|
||||
if (img_convert_ctx == NULL)
|
||||
return false;//CV_Error(0, "Cannot initialize the conversion context!");
|
||||
|
||||
#if USE_AV_FRAME_GET_BUFFER
|
||||
av_frame_unref(&rgb_picture);
|
||||
rgb_picture.format = AV_PIX_FMT_BGR24;
|
||||
rgb_picture.width = buffer_width;
|
||||
rgb_picture.height = buffer_height;
|
||||
if (0 != av_frame_get_buffer(&rgb_picture, 32))
|
||||
{
|
||||
CV_WARN("OutOfMemory");
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
int aligns[AV_NUM_DATA_POINTERS];
|
||||
avcodec_align_dimensions2(video_st->codec, &buffer_width, &buffer_height, aligns);
|
||||
rgb_picture.data[0] = (uint8_t*)realloc(rgb_picture.data[0],
|
||||
avpicture_get_size( AV_PIX_FMT_BGR24,
|
||||
buffer_width, buffer_height ));
|
||||
avpicture_fill( (AVPicture*)&rgb_picture, rgb_picture.data[0],
|
||||
AV_PIX_FMT_BGR24, buffer_width, buffer_height );
|
||||
#endif
|
||||
frame.width = video_st->codec->width;
|
||||
frame.height = video_st->codec->height;
|
||||
frame.cn = 3;
|
||||
frame.data = rgb_picture.data[0];
|
||||
frame.step = rgb_picture.linesize[0];
|
||||
}
|
||||
|
||||
sws_scale(
|
||||
img_convert_ctx,
|
||||
picture->data,
|
||||
picture->linesize,
|
||||
0, video_st->codec->height,
|
||||
0, video_st->codec->coded_height,
|
||||
rgb_picture.data,
|
||||
rgb_picture.linesize
|
||||
);
|
||||
@@ -1005,7 +1246,7 @@ struct CvVideoWriter_FFMPEG
|
||||
uint8_t * picbuf;
|
||||
AVStream * video_st;
|
||||
int input_pix_fmt;
|
||||
Image_FFMPEG temp_image;
|
||||
unsigned char * aligned_input;
|
||||
int frame_width, frame_height;
|
||||
int frame_idx;
|
||||
bool ok;
|
||||
@@ -1082,7 +1323,7 @@ void CvVideoWriter_FFMPEG::init()
|
||||
picbuf = 0;
|
||||
video_st = 0;
|
||||
input_pix_fmt = 0;
|
||||
memset(&temp_image, 0, sizeof(temp_image));
|
||||
aligned_input = NULL;
|
||||
img_convert_ctx = 0;
|
||||
frame_width = frame_height = 0;
|
||||
frame_idx = 0;
|
||||
@@ -1099,10 +1340,20 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo
|
||||
uint8_t * picture_buf;
|
||||
int size;
|
||||
|
||||
#if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \
|
||||
? CALC_FFMPEG_VERSION(55, 45, 101) : CALC_FFMPEG_VERSION(55, 28, 1))
|
||||
picture = av_frame_alloc();
|
||||
#else
|
||||
picture = avcodec_alloc_frame();
|
||||
#endif
|
||||
if (!picture)
|
||||
return NULL;
|
||||
size = avpicture_get_size( (PixelFormat) pix_fmt, width, height);
|
||||
|
||||
picture->format = pix_fmt;
|
||||
picture->width = width;
|
||||
picture->height = height;
|
||||
|
||||
size = avpicture_get_size( (AVPixelFormat) pix_fmt, width, height);
|
||||
if(alloc){
|
||||
picture_buf = (uint8_t *) malloc(size);
|
||||
if (!picture_buf)
|
||||
@@ -1111,7 +1362,7 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo
|
||||
return NULL;
|
||||
}
|
||||
avpicture_fill((AVPicture *)picture, picture_buf,
|
||||
(PixelFormat) pix_fmt, width, height);
|
||||
(AVPixelFormat) pix_fmt, width, height);
|
||||
}
|
||||
else {
|
||||
}
|
||||
@@ -1211,7 +1462,7 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
|
||||
#endif
|
||||
|
||||
c->gop_size = 12; /* emit one intra frame every twelve frames at most */
|
||||
c->pix_fmt = (PixelFormat) pixel_format;
|
||||
c->pix_fmt = (AVPixelFormat) pixel_format;
|
||||
|
||||
if (c->codec_id == CV_CODEC(CODEC_ID_MPEG2VIDEO)) {
|
||||
c->max_b_frames = 2;
|
||||
@@ -1318,7 +1569,20 @@ static int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st,
|
||||
/// write a frame with FFMPEG
|
||||
bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int width, int height, int cn, int origin )
|
||||
{
|
||||
bool ret = false;
|
||||
// check parameters
|
||||
if (input_pix_fmt == AV_PIX_FMT_BGR24) {
|
||||
if (cn != 3) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (input_pix_fmt == AV_PIX_FMT_GRAY8) {
|
||||
if (cn != 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
if( (width & -2) != frame_width || (height & -2) != frame_height || !data )
|
||||
return false;
|
||||
@@ -1332,71 +1596,43 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int
|
||||
AVCodecContext *c = &(video_st->codec);
|
||||
#endif
|
||||
|
||||
#if LIBAVFORMAT_BUILD < 5231
|
||||
// It is not needed in the latest versions of the ffmpeg
|
||||
if( c->codec_id == CV_CODEC(CODEC_ID_RAWVIDEO) && origin != 1 )
|
||||
// FFmpeg contains SIMD optimizations which can sometimes read data past
|
||||
// the supplied input buffer. To ensure that doesn't happen, we pad the
|
||||
// step to a multiple of 32 (that's the minimal alignment for which Valgrind
|
||||
// doesn't raise any warnings).
|
||||
const int STEP_ALIGNMENT = 32;
|
||||
if( step % STEP_ALIGNMENT != 0 )
|
||||
{
|
||||
if( !temp_image.data )
|
||||
int aligned_step = (step + STEP_ALIGNMENT - 1) & -STEP_ALIGNMENT;
|
||||
|
||||
if( !aligned_input )
|
||||
{
|
||||
temp_image.step = (width*cn + 3) & -4;
|
||||
temp_image.width = width;
|
||||
temp_image.height = height;
|
||||
temp_image.cn = cn;
|
||||
temp_image.data = (unsigned char*)malloc(temp_image.step*temp_image.height);
|
||||
}
|
||||
for( int y = 0; y < height; y++ )
|
||||
memcpy(temp_image.data + y*temp_image.step, data + (height-1-y)*step, width*cn);
|
||||
data = temp_image.data;
|
||||
step = temp_image.step;
|
||||
}
|
||||
#else
|
||||
if( width*cn != step )
|
||||
{
|
||||
if( !temp_image.data )
|
||||
{
|
||||
temp_image.step = width*cn;
|
||||
temp_image.width = width;
|
||||
temp_image.height = height;
|
||||
temp_image.cn = cn;
|
||||
temp_image.data = (unsigned char*)malloc(temp_image.step*temp_image.height);
|
||||
aligned_input = (unsigned char*)av_mallocz(aligned_step * height);
|
||||
}
|
||||
|
||||
if (origin == 1)
|
||||
for( int y = 0; y < height; y++ )
|
||||
memcpy(temp_image.data + y*temp_image.step, data + (height-1-y)*step, temp_image.step);
|
||||
memcpy(aligned_input + y*aligned_step, data + (height-1-y)*step, step);
|
||||
else
|
||||
for( int y = 0; y < height; y++ )
|
||||
memcpy(temp_image.data + y*temp_image.step, data + y*step, temp_image.step);
|
||||
data = temp_image.data;
|
||||
step = temp_image.step;
|
||||
}
|
||||
#endif
|
||||
memcpy(aligned_input + y*aligned_step, data + y*step, step);
|
||||
|
||||
// check parameters
|
||||
if (input_pix_fmt == PIX_FMT_BGR24) {
|
||||
if (cn != 3) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (input_pix_fmt == PIX_FMT_GRAY8) {
|
||||
if (cn != 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
data = aligned_input;
|
||||
step = aligned_step;
|
||||
}
|
||||
|
||||
if ( c->pix_fmt != input_pix_fmt ) {
|
||||
assert( input_picture );
|
||||
// let input_picture point to the raw data buffer of 'image'
|
||||
avpicture_fill((AVPicture *)input_picture, (uint8_t *) data,
|
||||
(PixelFormat)input_pix_fmt, width, height);
|
||||
(AVPixelFormat)input_pix_fmt, width, height);
|
||||
input_picture->linesize[0] = step;
|
||||
|
||||
if( !img_convert_ctx )
|
||||
{
|
||||
img_convert_ctx = sws_getContext(width,
|
||||
height,
|
||||
(PixelFormat)input_pix_fmt,
|
||||
(AVPixelFormat)input_pix_fmt,
|
||||
c->width,
|
||||
c->height,
|
||||
c->pix_fmt,
|
||||
@@ -1414,11 +1650,12 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int
|
||||
}
|
||||
else{
|
||||
avpicture_fill((AVPicture *)picture, (uint8_t *) data,
|
||||
(PixelFormat)input_pix_fmt, width, height);
|
||||
(AVPixelFormat)input_pix_fmt, width, height);
|
||||
picture->linesize[0] = step;
|
||||
}
|
||||
|
||||
picture->pts = frame_idx;
|
||||
ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, picture) >= 0;
|
||||
bool ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, picture) >= 0;
|
||||
frame_idx++;
|
||||
|
||||
return ret;
|
||||
@@ -1501,11 +1738,7 @@ void CvVideoWriter_FFMPEG::close()
|
||||
/* free the stream */
|
||||
avformat_free_context(oc);
|
||||
|
||||
if( temp_image.data )
|
||||
{
|
||||
free(temp_image.data);
|
||||
temp_image.data = 0;
|
||||
}
|
||||
av_freep(&aligned_input);
|
||||
|
||||
init();
|
||||
}
|
||||
@@ -1547,10 +1780,10 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
|
||||
|
||||
/* determine optimal pixel format */
|
||||
if (is_color) {
|
||||
input_pix_fmt = PIX_FMT_BGR24;
|
||||
input_pix_fmt = AV_PIX_FMT_BGR24;
|
||||
}
|
||||
else {
|
||||
input_pix_fmt = PIX_FMT_GRAY8;
|
||||
input_pix_fmt = AV_PIX_FMT_GRAY8;
|
||||
}
|
||||
|
||||
/* Lookup codec_id for given fourcc */
|
||||
@@ -1587,21 +1820,21 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
|
||||
break;
|
||||
#endif
|
||||
case CV_CODEC(CODEC_ID_HUFFYUV):
|
||||
codec_pix_fmt = PIX_FMT_YUV422P;
|
||||
codec_pix_fmt = AV_PIX_FMT_YUV422P;
|
||||
break;
|
||||
case CV_CODEC(CODEC_ID_MJPEG):
|
||||
case CV_CODEC(CODEC_ID_LJPEG):
|
||||
codec_pix_fmt = PIX_FMT_YUVJ420P;
|
||||
codec_pix_fmt = AV_PIX_FMT_YUVJ420P;
|
||||
bitrate_scale = 3;
|
||||
break;
|
||||
case CV_CODEC(CODEC_ID_RAWVIDEO):
|
||||
codec_pix_fmt = input_pix_fmt == PIX_FMT_GRAY8 ||
|
||||
input_pix_fmt == PIX_FMT_GRAY16LE ||
|
||||
input_pix_fmt == PIX_FMT_GRAY16BE ? input_pix_fmt : PIX_FMT_YUV420P;
|
||||
codec_pix_fmt = input_pix_fmt == AV_PIX_FMT_GRAY8 ||
|
||||
input_pix_fmt == AV_PIX_FMT_GRAY16LE ||
|
||||
input_pix_fmt == AV_PIX_FMT_GRAY16BE ? input_pix_fmt : AV_PIX_FMT_YUV420P;
|
||||
break;
|
||||
default:
|
||||
// good for lossy formats, MPEG, etc.
|
||||
codec_pix_fmt = PIX_FMT_YUV420P;
|
||||
codec_pix_fmt = AV_PIX_FMT_YUV420P;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1826,7 +2059,7 @@ struct OutputMediaStream_FFMPEG
|
||||
void write(unsigned char* data, int size, int keyFrame);
|
||||
|
||||
// add a video output stream to the container
|
||||
static AVStream* addVideoStream(AVFormatContext *oc, CV_CODEC_ID codec_id, int w, int h, int bitrate, double fps, PixelFormat pixel_format);
|
||||
static AVStream* addVideoStream(AVFormatContext *oc, CV_CODEC_ID codec_id, int w, int h, int bitrate, double fps, AVPixelFormat pixel_format);
|
||||
|
||||
AVOutputFormat* fmt_;
|
||||
AVFormatContext* oc_;
|
||||
@@ -1873,7 +2106,7 @@ void OutputMediaStream_FFMPEG::close()
|
||||
}
|
||||
}
|
||||
|
||||
AVStream* OutputMediaStream_FFMPEG::addVideoStream(AVFormatContext *oc, CV_CODEC_ID codec_id, int w, int h, int bitrate, double fps, PixelFormat pixel_format)
|
||||
AVStream* OutputMediaStream_FFMPEG::addVideoStream(AVFormatContext *oc, CV_CODEC_ID codec_id, int w, int h, int bitrate, double fps, AVPixelFormat pixel_format)
|
||||
{
|
||||
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 10, 0)
|
||||
AVStream* st = avformat_new_stream(oc, 0);
|
||||
@@ -2011,7 +2244,7 @@ bool OutputMediaStream_FFMPEG::open(const char* fileName, int width, int height,
|
||||
oc_->max_delay = (int)(0.7 * AV_TIME_BASE); // This reduces buffer underrun warnings with MPEG
|
||||
|
||||
// set a few optimal pixel formats for lossless codecs of interest..
|
||||
PixelFormat codec_pix_fmt = PIX_FMT_YUV420P;
|
||||
AVPixelFormat codec_pix_fmt = AV_PIX_FMT_YUV420P;
|
||||
int bitrate_scale = 64;
|
||||
|
||||
// TODO -- safe to ignore output audio stream?
|
||||
@@ -2150,6 +2383,10 @@ private:
|
||||
AVFormatContext* ctx_;
|
||||
int video_stream_id_;
|
||||
AVPacket pkt_;
|
||||
|
||||
#if USE_AV_INTERRUPT_CALLBACK
|
||||
AVInterruptCallbackMetadata interrupt_metadata;
|
||||
#endif
|
||||
};
|
||||
|
||||
bool InputMediaStream_FFMPEG::open(const char* fileName, int* codec, int* chroma_format, int* width, int* height)
|
||||
@@ -2160,6 +2397,16 @@ bool InputMediaStream_FFMPEG::open(const char* fileName, int* codec, int* chroma
|
||||
video_stream_id_ = -1;
|
||||
memset(&pkt_, 0, sizeof(AVPacket));
|
||||
|
||||
#if USE_AV_INTERRUPT_CALLBACK
|
||||
/* interrupt callback */
|
||||
interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_OPEN_TIMEOUT_MS;
|
||||
get_monotonic_time(&interrupt_metadata.value);
|
||||
|
||||
ctx_ = avformat_alloc_context();
|
||||
ctx_->interrupt_callback.callback = _opencv_ffmpeg_interrupt_callback;
|
||||
ctx_->interrupt_callback.opaque = &interrupt_metadata;
|
||||
#endif
|
||||
|
||||
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)
|
||||
avformat_network_init();
|
||||
#endif
|
||||
@@ -2220,15 +2467,15 @@ bool InputMediaStream_FFMPEG::open(const char* fileName, int* codec, int* chroma
|
||||
|
||||
switch (enc->pix_fmt)
|
||||
{
|
||||
case PIX_FMT_YUV420P:
|
||||
case AV_PIX_FMT_YUV420P:
|
||||
*chroma_format = ::VideoChromaFormat_YUV420;
|
||||
break;
|
||||
|
||||
case PIX_FMT_YUV422P:
|
||||
case AV_PIX_FMT_YUV422P:
|
||||
*chroma_format = ::VideoChromaFormat_YUV422;
|
||||
break;
|
||||
|
||||
case PIX_FMT_YUV444P:
|
||||
case AV_PIX_FMT_YUV444P:
|
||||
*chroma_format = ::VideoChromaFormat_YUV444;
|
||||
break;
|
||||
|
||||
@@ -2248,6 +2495,11 @@ bool InputMediaStream_FFMPEG::open(const char* fileName, int* codec, int* chroma
|
||||
|
||||
av_init_packet(&pkt_);
|
||||
|
||||
#if USE_AV_INTERRUPT_CALLBACK
|
||||
// deactivate interrupt callback
|
||||
interrupt_metadata.timeout_after_ms = 0;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2269,6 +2521,14 @@ void InputMediaStream_FFMPEG::close()
|
||||
|
||||
bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFile)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
#if USE_AV_INTERRUPT_CALLBACK
|
||||
// activate interrupt callback
|
||||
get_monotonic_time(&interrupt_metadata.value);
|
||||
interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_READ_TIMEOUT_MS;
|
||||
#endif
|
||||
|
||||
// free last packet if exist
|
||||
if (pkt_.data)
|
||||
av_free_packet(&pkt_);
|
||||
@@ -2276,6 +2536,13 @@ bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFi
|
||||
// get the next frame
|
||||
for (;;)
|
||||
{
|
||||
#if USE_AV_INTERRUPT_CALLBACK
|
||||
if(interrupt_metadata.timeout)
|
||||
{
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
int ret = av_read_frame(ctx_, &pkt_);
|
||||
|
||||
if (ret == AVERROR(EAGAIN))
|
||||
@@ -2285,7 +2552,7 @@ bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFi
|
||||
{
|
||||
if (ret == (int)AVERROR_EOF)
|
||||
*endOfFile = true;
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pkt_.stream_index != video_stream_id_)
|
||||
@@ -2294,14 +2561,23 @@ bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFi
|
||||
continue;
|
||||
}
|
||||
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
|
||||
*data = pkt_.data;
|
||||
*size = pkt_.size;
|
||||
*endOfFile = false;
|
||||
#if USE_AV_INTERRUPT_CALLBACK
|
||||
// deactivate interrupt callback
|
||||
interrupt_metadata.timeout_after_ms = 0;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
if (result)
|
||||
{
|
||||
*data = pkt_.data;
|
||||
*size = pkt_.size;
|
||||
*endOfFile = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
InputMediaStream_FFMPEG* create_InputMediaStream_FFMPEG(const char* fileName, int* codec, int* chroma_format, int* width, int* height)
|
||||
|
||||
@@ -95,6 +95,8 @@ didDropVideoFrameWithSampleBuffer:(QTSampleBuffer *)sampleBuffer
|
||||
- (int)updateImage;
|
||||
- (IplImage*)getOutput;
|
||||
|
||||
- (void)doFireTimer:(NSTimer *)timer;
|
||||
|
||||
@end
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -625,6 +627,11 @@ didDropVideoFrameWithSampleBuffer:(QTSampleBuffer *)sampleBuffer
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (void)doFireTimer:(NSTimer *)timer {
|
||||
(void)timer;
|
||||
// dummy
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@@ -491,8 +491,6 @@ static int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName)
|
||||
// 0 then detected nothing
|
||||
// 1 then V4L2 device
|
||||
|
||||
int deviceIndex;
|
||||
|
||||
/* Open and test V4L2 device */
|
||||
capture->deviceHandle = open (deviceName, O_RDWR /* required */ | O_NONBLOCK, 0);
|
||||
if (-1 == capture->deviceHandle)
|
||||
@@ -514,28 +512,6 @@ static int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Query channels number */
|
||||
if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_INPUT, &deviceIndex))
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
fprintf(stderr, "(DEBUG) try_init_v4l2 VIDIOC_G_INPUT \"%s\": %s\n", deviceName, strerror(errno));
|
||||
#endif
|
||||
icvCloseCAM_V4L(capture);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Query information about current input */
|
||||
CLEAR (capture->inp);
|
||||
capture->inp.index = deviceIndex;
|
||||
if (-1 == ioctl (capture->deviceHandle, VIDIOC_ENUMINPUT, &capture->inp))
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
fprintf(stderr, "(DEBUG) try_init_v4l2 VIDIOC_ENUMINPUT \"%s\": %s\n", deviceName, strerror(errno));
|
||||
#endif
|
||||
icvCloseCAM_V4L(capture);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
@@ -834,26 +810,6 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The following code sets the CHANNEL_NUMBER of the video input. Some video sources
|
||||
have sub "Channel Numbers". For a typical V4L TV capture card, this is usually 1.
|
||||
I myself am using a simple NTSC video input capture card that uses the value of 1.
|
||||
If you are not in North America or have a different video standard, you WILL have to change
|
||||
the following settings and recompile/reinstall. This set of settings is based on
|
||||
the most commonly encountered input video source types (like my bttv card) */
|
||||
|
||||
if(capture->inp.index > 0) {
|
||||
CLEAR (capture->inp);
|
||||
capture->inp.index = CHANNEL_NUMBER;
|
||||
/* Set only channel number to CHANNEL_NUMBER */
|
||||
/* V4L2 have a status field from selected video mode */
|
||||
if (-1 == ioctl (capture->deviceHandle, VIDIOC_ENUMINPUT, &capture->inp))
|
||||
{
|
||||
fprintf (stderr, "HIGHGUI ERROR: V4L2: Aren't able to set channel number\n");
|
||||
icvCloseCAM_V4L (capture);
|
||||
return -1;
|
||||
}
|
||||
} /* End if */
|
||||
|
||||
/* Find Window info */
|
||||
CLEAR (capture->form);
|
||||
capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
@@ -1157,6 +1113,9 @@ static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index)
|
||||
}
|
||||
#endif /* HAVE_CAMV4L */
|
||||
#ifdef HAVE_CAMV4L2
|
||||
#ifndef HAVE_CAMV4L
|
||||
return NULL;
|
||||
#endif /* !HAVE_CAMV4L */
|
||||
} else {
|
||||
V4L2_SUPPORT = 1;
|
||||
}
|
||||
|
||||
@@ -502,7 +502,7 @@ bool Jpeg2KEncoder::writeComponent16u( void *__img, const Mat& _img )
|
||||
|
||||
for( int y = 0; y < h; y++ )
|
||||
{
|
||||
uchar* data = _img.data + _img.step*y;
|
||||
const ushort* data = _img.ptr<ushort>(y);
|
||||
for( int i = 0; i < ncmpts; i++ )
|
||||
{
|
||||
for( int x = 0; x < w; x++)
|
||||
|
||||
@@ -228,8 +228,6 @@ bool PngDecoder::readData( Mat& img )
|
||||
AutoBuffer<uchar*> _buffer(m_height);
|
||||
uchar** buffer = _buffer;
|
||||
int color = img.channels() > 1;
|
||||
uchar* data = img.data;
|
||||
int step = (int)img.step;
|
||||
|
||||
if( m_png_ptr && m_info_ptr && m_end_info && m_width && m_height )
|
||||
{
|
||||
@@ -281,7 +279,7 @@ bool PngDecoder::readData( Mat& img )
|
||||
png_read_update_info( png_ptr, info_ptr );
|
||||
|
||||
for( y = 0; y < m_height; y++ )
|
||||
buffer[y] = data + y*step;
|
||||
buffer[y] = img.data + y*img.step;
|
||||
|
||||
png_read_image( png_ptr, buffer );
|
||||
png_read_end( png_ptr, end_info );
|
||||
|
||||
@@ -1007,13 +1007,33 @@ static void icvDeleteWindow( CvWindow* window )
|
||||
}
|
||||
|
||||
cvFree( &window );
|
||||
|
||||
// if last window...
|
||||
if( hg_windows == 0 )
|
||||
{
|
||||
#ifdef HAVE_GTHREAD
|
||||
// if last window, send key press signal
|
||||
// to jump out of any waiting cvWaitKey's
|
||||
if(hg_windows==0 && thread_started){
|
||||
g_cond_broadcast(cond_have_key);
|
||||
}
|
||||
if( thread_started )
|
||||
{
|
||||
// send key press signal to jump out of any waiting cvWaitKey's
|
||||
g_cond_broadcast( cond_have_key );
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
// Some GTK+ modules (like the Unity module) use GDBusConnection,
|
||||
// which has a habit of postponing cleanup by performing it via
|
||||
// idle sources added to the main loop. Since this was the last window,
|
||||
// we can assume that no event processing is going to happen in the
|
||||
// nearest future, so we should force that cleanup (by handling all pending
|
||||
// events) while we still have the chance.
|
||||
// This is not needed if thread_started is true, because the background
|
||||
// thread will process events continuously.
|
||||
while( gtk_events_pending() )
|
||||
gtk_main_iteration();
|
||||
#ifdef HAVE_GTHREAD
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -721,7 +721,10 @@ Computes the ideal point coordinates from the observed point coordinates.
|
||||
|
||||
.. ocv:function:: void undistortPoints( InputArray src, OutputArray dst, InputArray cameraMatrix, InputArray distCoeffs, InputArray R=noArray(), InputArray P=noArray())
|
||||
|
||||
.. ocv:pyfunction:: cv2.undistortPoints(src, cameraMatrix, distCoeffs[, dst[, R[, P]]]) -> dst
|
||||
|
||||
.. ocv:cfunction:: void cvUndistortPoints( const CvMat* src, CvMat* dst, const CvMat* camera_matrix, const CvMat* dist_coeffs, const CvMat* R=0, const CvMat* P=0 )
|
||||
|
||||
.. ocv:pyoldfunction:: cv.UndistortPoints(src, dst, cameraMatrix, distCoeffs, R=None, P=None)-> None
|
||||
|
||||
:param src: Observed point coordinates, 1xN or Nx1 2-channel (CV_32FC2 or CV_64FC2).
|
||||
|
||||
@@ -584,19 +584,11 @@ typedef MorphFVec<VMax32f> DilateVec32f;
|
||||
|
||||
#else
|
||||
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
using tegra::ErodeRowVec8u;
|
||||
using tegra::DilateRowVec8u;
|
||||
|
||||
using tegra::ErodeColumnVec8u;
|
||||
using tegra::DilateColumnVec8u;
|
||||
#else
|
||||
typedef MorphRowNoVec ErodeRowVec8u;
|
||||
typedef MorphRowNoVec DilateRowVec8u;
|
||||
|
||||
typedef MorphColumnNoVec ErodeColumnVec8u;
|
||||
typedef MorphColumnNoVec DilateColumnVec8u;
|
||||
#endif
|
||||
|
||||
typedef MorphRowNoVec ErodeRowVec16u;
|
||||
typedef MorphRowNoVec DilateRowVec16u;
|
||||
@@ -1114,6 +1106,17 @@ public:
|
||||
Mat srcStripe = src.rowRange(row0, row1);
|
||||
Mat dstStripe = dst.rowRange(row0, row1);
|
||||
|
||||
|
||||
#if defined HAVE_TEGRA_OPTIMIZATION
|
||||
//Iterative separable filters are converted to single iteration filters
|
||||
//But anyway check that we really get 1 iteration prior to processing
|
||||
if( countNonZero(kernel) == kernel.rows*kernel.cols && iterations == 1 &&
|
||||
src.depth() == CV_8U && ( op == MORPH_ERODE || op == MORPH_DILATE ) &&
|
||||
tegra::morphology(srcStripe, dstStripe, op, kernel, anchor,
|
||||
rowBorderType, columnBorderType, borderValue) )
|
||||
return;
|
||||
#endif
|
||||
|
||||
Ptr<FilterEngine> f = createMorphologyFilter(op, src.type(), kernel, anchor,
|
||||
rowBorderType, columnBorderType, borderValue );
|
||||
|
||||
|
||||
@@ -349,7 +349,7 @@ pyrUp_( const Mat& _src, Mat& _dst, int)
|
||||
for( ; sy <= y + 1; sy++ )
|
||||
{
|
||||
WT* row = buf + ((sy - sy0) % PU_SZ)*bufstep;
|
||||
int _sy = borderInterpolate(sy*2, dsize.height, BORDER_REFLECT_101)/2;
|
||||
int _sy = borderInterpolate(sy*2, ssize.height*2, BORDER_REFLECT_101)/2;
|
||||
const T* src = (const T*)(_src.data + _src.step*_sy);
|
||||
|
||||
if( ssize.width == cn )
|
||||
@@ -370,6 +370,11 @@ pyrUp_( const Mat& _src, Mat& _dst, int)
|
||||
t0 = src[sx - cn] + src[sx]*7;
|
||||
t1 = src[sx]*8;
|
||||
row[dx] = t0; row[dx + cn] = t1;
|
||||
|
||||
if (dsize.width > ssize.width*2)
|
||||
{
|
||||
row[(_dst.cols-1) + x] = row[dx + cn];
|
||||
}
|
||||
}
|
||||
|
||||
for( x = cn; x < ssize.width - cn; x++ )
|
||||
@@ -395,6 +400,17 @@ pyrUp_( const Mat& _src, Mat& _dst, int)
|
||||
dst1[x] = t1; dst0[x] = t0;
|
||||
}
|
||||
}
|
||||
|
||||
if (dsize.height > ssize.height*2)
|
||||
{
|
||||
T* dst0 = _dst.ptr<T>(ssize.height*2-2);
|
||||
T* dst2 = _dst.ptr<T>(ssize.height*2);
|
||||
|
||||
for(x = 0; x < dsize.width ; x++ )
|
||||
{
|
||||
dst2[x] = dst0[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*PyrFunc)(const Mat&, Mat&, int);
|
||||
|
||||
@@ -130,8 +130,8 @@ static void icvMaxRoi1( _CvRect16u *max_rect, int x, int y );
|
||||
(float)fabs((a).green - (b).green), \
|
||||
(float)fabs((a).blue - (b).blue))*/
|
||||
|
||||
#define _CV_NEXT_BASE_C1(p,n) (_CvPyramid*)((char*)(p) + (n)*sizeof(_CvPyramidBase))
|
||||
#define _CV_NEXT_BASE_C3(p,n) (_CvPyramidC3*)((char*)(p) + (n)*sizeof(_CvPyramidBaseC3))
|
||||
#define _CV_NEXT_BASE_C1(p,n) ((_CvPyramid*)((char*)(p) + (n)*(ptrdiff_t)sizeof(_CvPyramidBase)))
|
||||
#define _CV_NEXT_BASE_C3(p,n) ((_CvPyramidC3*)((char*)(p) + (n)*(ptrdiff_t)sizeof(_CvPyramidBaseC3)))
|
||||
|
||||
|
||||
CV_INLINE float icvRGBDist_Max( const _CvRGBf& a, const _CvRGBf& b )
|
||||
@@ -868,7 +868,7 @@ icvPyrSegmentation8uC3R( uchar * src_image, int src_step,
|
||||
|
||||
if( p_cur[size.width].a == 0 )
|
||||
{
|
||||
p_cur[size.width].c = p_prev[(l != 0) - 1].c;
|
||||
p_cur[size.width].c = (l != 0) ? p_prev->c : _CV_NEXT_BASE_C3( p_prev, -1 )->c;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
import cv2.cv as cv
|
||||
|
||||
from tests_common import OpenCVTests
|
||||
|
||||
class NonFreeFunctionTests(OpenCVTests):
|
||||
|
||||
def test_ExtractSURF(self):
|
||||
img = self.get_sample("samples/c/lena.jpg", 0)
|
||||
w,h = cv.GetSize(img)
|
||||
for hessthresh in [ 300,400,500]:
|
||||
for dsize in [0,1]:
|
||||
for layers in [1,3,10]:
|
||||
kp,desc = cv.ExtractSURF(img, None, cv.CreateMemStorage(), (dsize, hessthresh, 3, layers))
|
||||
self.assertTrue(len(kp) == len(desc))
|
||||
for d in desc:
|
||||
self.assertTrue(len(d) == {0:64, 1:128}[dsize])
|
||||
for pt,laplacian,size,dir,hessian in kp:
|
||||
self.assertTrue((0 <= pt[0]) and (pt[0] <= w))
|
||||
self.assertTrue((0 <= pt[1]) and (pt[1] <= h))
|
||||
self.assertTrue(laplacian in [-1, 0, 1])
|
||||
self.assertTrue((0 <= dir) and (dir <= 360))
|
||||
self.assertTrue(hessian >= hessthresh)
|
||||
+23
-150
@@ -17,110 +17,15 @@ import argparse
|
||||
|
||||
import cv2.cv as cv
|
||||
|
||||
from test2 import *
|
||||
from tests_common import OpenCVTests, NewOpenCVTests
|
||||
|
||||
class OpenCVTests(unittest.TestCase):
|
||||
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
# path to local repository folder containing 'samples' folder
|
||||
repoPath = None
|
||||
# github repository url
|
||||
repoUrl = 'https://raw.github.com/Itseez/opencv/2.4'
|
||||
# path to local folder containing 'camera_calibration.tar.gz'
|
||||
dataPath = None
|
||||
# data url
|
||||
dataUrl = 'http://docs.opencv.org/data'
|
||||
|
||||
depths = [ cv.IPL_DEPTH_8U, cv.IPL_DEPTH_8S, cv.IPL_DEPTH_16U, cv.IPL_DEPTH_16S, cv.IPL_DEPTH_32S, cv.IPL_DEPTH_32F, cv.IPL_DEPTH_64F ]
|
||||
|
||||
mat_types = [
|
||||
cv.CV_8UC1,
|
||||
cv.CV_8UC2,
|
||||
cv.CV_8UC3,
|
||||
cv.CV_8UC4,
|
||||
cv.CV_8SC1,
|
||||
cv.CV_8SC2,
|
||||
cv.CV_8SC3,
|
||||
cv.CV_8SC4,
|
||||
cv.CV_16UC1,
|
||||
cv.CV_16UC2,
|
||||
cv.CV_16UC3,
|
||||
cv.CV_16UC4,
|
||||
cv.CV_16SC1,
|
||||
cv.CV_16SC2,
|
||||
cv.CV_16SC3,
|
||||
cv.CV_16SC4,
|
||||
cv.CV_32SC1,
|
||||
cv.CV_32SC2,
|
||||
cv.CV_32SC3,
|
||||
cv.CV_32SC4,
|
||||
cv.CV_32FC1,
|
||||
cv.CV_32FC2,
|
||||
cv.CV_32FC3,
|
||||
cv.CV_32FC4,
|
||||
cv.CV_64FC1,
|
||||
cv.CV_64FC2,
|
||||
cv.CV_64FC3,
|
||||
cv.CV_64FC4,
|
||||
]
|
||||
mat_types_single = [
|
||||
cv.CV_8UC1,
|
||||
cv.CV_8SC1,
|
||||
cv.CV_16UC1,
|
||||
cv.CV_16SC1,
|
||||
cv.CV_32SC1,
|
||||
cv.CV_32FC1,
|
||||
cv.CV_64FC1,
|
||||
]
|
||||
|
||||
def depthsize(self, d):
|
||||
return { cv.IPL_DEPTH_8U : 1,
|
||||
cv.IPL_DEPTH_8S : 1,
|
||||
cv.IPL_DEPTH_16U : 2,
|
||||
cv.IPL_DEPTH_16S : 2,
|
||||
cv.IPL_DEPTH_32S : 4,
|
||||
cv.IPL_DEPTH_32F : 4,
|
||||
cv.IPL_DEPTH_64F : 8 }[d]
|
||||
|
||||
def get_sample(self, filename, iscolor = cv.CV_LOAD_IMAGE_COLOR):
|
||||
if not filename in self.image_cache:
|
||||
filedata = None
|
||||
if OpenCVTests.repoPath is not None:
|
||||
candidate = OpenCVTests.repoPath + '/' + filename
|
||||
if os.path.isfile(candidate):
|
||||
with open(candidate, 'rb') as f:
|
||||
filedata = f.read()
|
||||
if filedata is None:
|
||||
filedata = urllib.urlopen(OpenCVTests.repoUrl + '/' + filename).read()
|
||||
imagefiledata = cv.CreateMatHeader(1, len(filedata), cv.CV_8UC1)
|
||||
cv.SetData(imagefiledata, filedata, len(filedata))
|
||||
self.image_cache[filename] = cv.DecodeImageM(imagefiledata, iscolor)
|
||||
return self.image_cache[filename]
|
||||
|
||||
def get_data(self, filename, urlbase):
|
||||
if (not os.path.isfile(filename)):
|
||||
if OpenCVTests.dataPath is not None:
|
||||
candidate = OpenCVTests.dataPath + '/' + filename
|
||||
if os.path.isfile(candidate):
|
||||
return candidate
|
||||
urllib.urlretrieve(urlbase + '/' + filename, filename)
|
||||
return filename
|
||||
|
||||
def setUp(self):
|
||||
self.image_cache = {}
|
||||
|
||||
def snap(self, img):
|
||||
self.snapL([img])
|
||||
|
||||
def snapL(self, L):
|
||||
for i,img in enumerate(L):
|
||||
cv.NamedWindow("snap-%d" % i, 1)
|
||||
cv.ShowImage("snap-%d" % i, img)
|
||||
cv.WaitKey()
|
||||
cv.DestroyAllWindows()
|
||||
|
||||
def hashimg(self, im):
|
||||
""" Compute a hash for an image, useful for image comparisons """
|
||||
return hashlib.md5(im.tostring()).digest()
|
||||
def load_tests(loader, tests, pattern):
|
||||
tests.addTests(loader.discover(basedir, pattern='nonfree_*.py'))
|
||||
tests.addTests(loader.discover(basedir, pattern='test_*.py'))
|
||||
tests.addTests(loader.discover(basedir, pattern='test2.py'))
|
||||
return tests
|
||||
|
||||
# Tests to run first; check the handful of basic operations that the later tests rely on
|
||||
|
||||
@@ -422,23 +327,6 @@ class FunctionTests(OpenCVTests):
|
||||
cv.SetZero(im)
|
||||
cv.DrawChessboardCorners(im, (5, 5), [ ((i/5)*100+50,(i%5)*100+50) for i in range(5 * 5) ], 1)
|
||||
|
||||
def test_ExtractSURF(self):
|
||||
img = self.get_sample("samples/c/lena.jpg", 0)
|
||||
w,h = cv.GetSize(img)
|
||||
for hessthresh in [ 300,400,500]:
|
||||
for dsize in [0,1]:
|
||||
for layers in [1,3,10]:
|
||||
kp,desc = cv.ExtractSURF(img, None, cv.CreateMemStorage(), (dsize, hessthresh, 3, layers))
|
||||
self.assert_(len(kp) == len(desc))
|
||||
for d in desc:
|
||||
self.assert_(len(d) == {0:64, 1:128}[dsize])
|
||||
for pt,laplacian,size,dir,hessian in kp:
|
||||
self.assert_((0 <= pt[0]) and (pt[0] <= w))
|
||||
self.assert_((0 <= pt[1]) and (pt[1] <= h))
|
||||
self.assert_(laplacian in [-1, 0, 1])
|
||||
self.assert_((0 <= dir) and (dir <= 360))
|
||||
self.assert_(hessian >= hessthresh)
|
||||
|
||||
def test_FillPoly(self):
|
||||
scribble = cv.CreateImage((640,480), cv.IPL_DEPTH_8U, 1)
|
||||
random.seed(0)
|
||||
@@ -1629,7 +1517,7 @@ class AreaTests(OpenCVTests):
|
||||
(0,255,0))
|
||||
self.snap(scribble)
|
||||
|
||||
def test_calibration(self):
|
||||
def xxx_test_calibration(self):
|
||||
|
||||
def get_corners(mono, refine = False):
|
||||
(ok, corners) = cv.FindChessboardCorners(mono, (num_x_ints, num_y_ints), cv.CV_CALIB_CB_ADAPTIVE_THRESH | cv.CV_CALIB_CB_NORMALIZE_IMAGE)
|
||||
@@ -2239,36 +2127,21 @@ if __name__ == '__main__':
|
||||
print "Local repo path:", args.repo
|
||||
print "Local data path:", args.data
|
||||
OpenCVTests.repoPath = args.repo
|
||||
OpenCVTests.dataPath = args.data
|
||||
NewOpenCVTests.repoPath = args.repo
|
||||
if args.repo is None:
|
||||
try:
|
||||
OpenCVTests.repoPath = os.environ['OPENCV_TEST_DATA_PATH']
|
||||
NewOpenCVTests.repoPath = OpenCVTests.repoPath
|
||||
except KeyError:
|
||||
print('Missing opencv samples data. Some of tests may fail.')
|
||||
try:
|
||||
OpenCVTests.dataPath = os.environ['OPENCV_TEST_DATA_PATH']
|
||||
NewOpenCVTests.extraTestDataPath = OpenCVTests.dataPath
|
||||
except KeyError:
|
||||
OpenCVTests.dataPath = args.data
|
||||
NewOpenCVTests.extraTestDataPath = args.data
|
||||
if args.data is None:
|
||||
print('Missing opencv extra repository. Some of tests may fail.')
|
||||
random.seed(0)
|
||||
unit_argv = [sys.argv[0]] + other;
|
||||
unittest.main(argv=unit_argv)
|
||||
# optlist, args = getopt.getopt(sys.argv[1:], 'l:rd')
|
||||
# loops = 1
|
||||
# shuffle = 0
|
||||
# doc_frags = False
|
||||
# for o,a in optlist:
|
||||
# if o == '-l':
|
||||
# loops = int(a)
|
||||
# if o == '-r':
|
||||
# shuffle = 1
|
||||
# if o == '-d':
|
||||
# doc_frags = True
|
||||
#
|
||||
# cases = [PreliminaryTests, FunctionTests, AreaTests]
|
||||
# if doc_frags:
|
||||
# cases += [DocumentFragmentTests]
|
||||
# everything = [(tc, t) for tc in cases for t in unittest.TestLoader().getTestCaseNames(tc) ]
|
||||
# if len(args) == 0:
|
||||
# # cases = [NewTests]
|
||||
# args = everything
|
||||
# else:
|
||||
# args = [(tc, t) for (tc, t) in everything if t in args]
|
||||
#
|
||||
# suite = unittest.TestSuite()
|
||||
# for l in range(loops):
|
||||
# if shuffle:
|
||||
# random.shuffle(args)
|
||||
# for tc,t in args:
|
||||
# suite.addTest(tc(t))
|
||||
# unittest.TextTestRunner(verbosity=2).run(suite)
|
||||
|
||||
@@ -8,22 +8,7 @@ import numpy as np
|
||||
import cv2
|
||||
import cv2.cv as cv
|
||||
|
||||
class NewOpenCVTests(unittest.TestCase):
|
||||
|
||||
def get_sample(self, filename, iscolor = cv.CV_LOAD_IMAGE_COLOR):
|
||||
if not filename in self.image_cache:
|
||||
filedata = urllib2.urlopen("https://raw.github.com/Itseez/opencv/2.4/" + filename).read()
|
||||
image = cv2.imdecode(np.fromstring(filedata, dtype=np.uint8), iscolor)
|
||||
self.assertFalse(image is None)
|
||||
self.image_cache[filename] = image
|
||||
return self.image_cache[filename]
|
||||
|
||||
def setUp(self):
|
||||
self.image_cache = {}
|
||||
|
||||
def hashimg(self, im):
|
||||
""" Compute a hash for an image, useful for image comparisons """
|
||||
return hashlib.md5(im.tostring()).digest()
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
# Tests to run first; check the handful of basic operations that the later tests rely on
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
camera calibration for distorted images with chess board samples
|
||||
reads distorted images, calculates the calibration and write undistorted images
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class calibration_test(NewOpenCVTests):
|
||||
|
||||
def test_calibration(self):
|
||||
|
||||
from glob import glob
|
||||
img_names = []
|
||||
for i in range(1, 15):
|
||||
if i < 10:
|
||||
img_names.append('samples/cpp/left0{}.jpg'.format(str(i)))
|
||||
elif i != 10:
|
||||
img_names.append('samples/cpp/left{}.jpg'.format(str(i)))
|
||||
|
||||
square_size = 1.0
|
||||
pattern_size = (9, 6)
|
||||
pattern_points = np.zeros((np.prod(pattern_size), 3), np.float32)
|
||||
pattern_points[:, :2] = np.indices(pattern_size).T.reshape(-1, 2)
|
||||
pattern_points *= square_size
|
||||
|
||||
obj_points = []
|
||||
img_points = []
|
||||
h, w = 0, 0
|
||||
img_names_undistort = []
|
||||
for fn in img_names:
|
||||
img = self.get_sample(fn, 0)
|
||||
if img is None:
|
||||
continue
|
||||
|
||||
h, w = img.shape[:2]
|
||||
found, corners = cv2.findChessboardCorners(img, pattern_size)
|
||||
if found:
|
||||
term = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT, 30, 0.1)
|
||||
cv2.cornerSubPix(img, corners, (5, 5), (-1, -1), term)
|
||||
|
||||
if not found:
|
||||
continue
|
||||
|
||||
img_points.append(corners.reshape(-1, 2))
|
||||
obj_points.append(pattern_points)
|
||||
|
||||
# calculate camera distortion
|
||||
rms, camera_matrix, dist_coefs, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, (w, h), None, None, flags = 0)
|
||||
|
||||
eps = 0.01
|
||||
normCamEps = 10.0
|
||||
normDistEps = 0.001
|
||||
|
||||
cameraMatrixTest = [[ 532.80992189, 0., 342.4952186 ],
|
||||
[ 0., 532.93346422, 233.8879292 ],
|
||||
[ 0., 0., 1. ]]
|
||||
|
||||
distCoeffsTest = [ -2.81325576e-01, 2.91130406e-02,
|
||||
1.21234330e-03, -1.40825372e-04, 1.54865844e-01]
|
||||
|
||||
self.assertLess(abs(rms - 0.196334638034), eps)
|
||||
self.assertLess(cv2.norm(camera_matrix - cameraMatrixTest, cv2.NORM_L1), normCamEps)
|
||||
self.assertLess(cv2.norm(dist_coefs - distCoeffsTest, cv2.NORM_L1), normDistEps)
|
||||
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
Camshift tracker
|
||||
================
|
||||
|
||||
This is a demo that shows mean-shift based tracking
|
||||
You select a color objects such as your face and it tracks it.
|
||||
This reads from video camera (0 by default, or the camera number the user enters)
|
||||
|
||||
http://www.robinhewitt.com/research/track/camshift.html
|
||||
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
if PY3:
|
||||
xrange = range
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
from tst_scene_render import TestSceneRender
|
||||
|
||||
from tests_common import NewOpenCVTests, intersectionRate
|
||||
|
||||
class camshift_test(NewOpenCVTests):
|
||||
|
||||
framesNum = 300
|
||||
frame = None
|
||||
selection = None
|
||||
drag_start = None
|
||||
show_backproj = False
|
||||
track_window = None
|
||||
render = None
|
||||
errors = 0
|
||||
|
||||
def prepareRender(self):
|
||||
|
||||
self.render = TestSceneRender(self.get_sample('samples/python2/data/pca_test1.jpg'), deformation = True)
|
||||
|
||||
def runTracker(self):
|
||||
|
||||
framesCounter = 0
|
||||
self.selection = True
|
||||
|
||||
xmin, ymin, xmax, ymax = self.render.getCurrentRect()
|
||||
|
||||
self.track_window = (xmin, ymin, xmax - xmin, ymax - ymin)
|
||||
|
||||
while True:
|
||||
framesCounter += 1
|
||||
self.frame = self.render.getNextFrame()
|
||||
hsv = cv2.cvtColor(self.frame, cv2.COLOR_BGR2HSV)
|
||||
mask = cv2.inRange(hsv, np.array((0., 60., 32.)), np.array((180., 255., 255.)))
|
||||
|
||||
if self.selection:
|
||||
x0, y0, x1, y1 = self.render.getCurrentRect() + 50
|
||||
x0 -= 100
|
||||
y0 -= 100
|
||||
|
||||
hsv_roi = hsv[y0:y1, x0:x1]
|
||||
mask_roi = mask[y0:y1, x0:x1]
|
||||
hist = cv2.calcHist( [hsv_roi], [0], mask_roi, [16], [0, 180] )
|
||||
cv2.normalize(hist, hist, 0, 255, cv2.NORM_MINMAX)
|
||||
self.hist = hist.reshape(-1)
|
||||
self.selection = False
|
||||
|
||||
if self.track_window and self.track_window[2] > 0 and self.track_window[3] > 0:
|
||||
self.selection = None
|
||||
prob = cv2.calcBackProject([hsv], [0], self.hist, [0, 180], 1)
|
||||
prob &= mask
|
||||
term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 )
|
||||
track_box, self.track_window = cv2.CamShift(prob, self.track_window, term_crit)
|
||||
|
||||
trackingRect = np.array(self.track_window)
|
||||
trackingRect[2] += trackingRect[0]
|
||||
trackingRect[3] += trackingRect[1]
|
||||
|
||||
if intersectionRate(self.render.getCurrentRect(), trackingRect) < 0.4:
|
||||
self.errors += 1
|
||||
|
||||
if framesCounter > self.framesNum:
|
||||
break
|
||||
|
||||
self.assertLess(float(self.errors) / self.framesNum, 0.4)
|
||||
|
||||
def test_camshift(self):
|
||||
self.prepareRender()
|
||||
self.runTracker()
|
||||
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
Test for disctrete fourier transform (dft)
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
import sys
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class dft_test(NewOpenCVTests):
|
||||
def test_dft(self):
|
||||
|
||||
img = self.get_sample('samples/gpu/rubberwhale1.png', 0)
|
||||
eps = 0.001
|
||||
|
||||
#test direct transform
|
||||
refDft = np.fft.fft2(img)
|
||||
refDftShift = np.fft.fftshift(refDft)
|
||||
refMagnitide = np.log(1.0 + np.abs(refDftShift))
|
||||
|
||||
testDft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT)
|
||||
testDftShift = np.fft.fftshift(testDft)
|
||||
testMagnitude = np.log(1.0 + cv2.magnitude(testDftShift[:,:,0], testDftShift[:,:,1]))
|
||||
|
||||
refMagnitide = cv2.normalize(refMagnitide, 0.0, 1.0, cv2.NORM_MINMAX)
|
||||
testMagnitude = cv2.normalize(testMagnitude, 0.0, 1.0, cv2.NORM_MINMAX)
|
||||
|
||||
self.assertLess(cv2.norm(refMagnitide - testMagnitude), eps)
|
||||
|
||||
#test inverse transform
|
||||
img_back = np.fft.ifft2(refDft)
|
||||
img_back = np.abs(img_back)
|
||||
|
||||
img_backTest = cv2.idft(testDft)
|
||||
img_backTest = cv2.magnitude(img_backTest[:,:,0], img_backTest[:,:,1])
|
||||
|
||||
img_backTest = cv2.normalize(img_backTest, 0.0, 1.0, cv2.NORM_MINMAX)
|
||||
img_back = cv2.normalize(img_back, 0.0, 1.0, cv2.NORM_MINMAX)
|
||||
|
||||
self.assertLess(cv2.norm(img_back - img_backTest), eps)
|
||||
@@ -0,0 +1,197 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
SVM and KNearest digit recognition.
|
||||
|
||||
Sample loads a dataset of handwritten digits from '../data/digits.png'.
|
||||
Then it trains a SVM and KNearest classifiers on it and evaluates
|
||||
their accuracy.
|
||||
|
||||
Following preprocessing is applied to the dataset:
|
||||
- Moment-based image deskew (see deskew())
|
||||
- Digit images are split into 4 10x10 cells and 16-bin
|
||||
histogram of oriented gradients is computed for each
|
||||
cell
|
||||
- Transform histograms to space with Hellinger metric (see [1] (RootSIFT))
|
||||
|
||||
|
||||
[1] R. Arandjelovic, A. Zisserman
|
||||
"Three things everyone should know to improve object retrieval"
|
||||
http://www.robots.ox.ac.uk/~vgg/publications/2012/Arandjelovic12/arandjelovic12.pdf
|
||||
|
||||
'''
|
||||
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
# built-in modules
|
||||
from multiprocessing.pool import ThreadPool
|
||||
|
||||
import cv2
|
||||
|
||||
import numpy as np
|
||||
from numpy.linalg import norm
|
||||
|
||||
|
||||
SZ = 20 # size of each digit is SZ x SZ
|
||||
CLASS_N = 10
|
||||
DIGITS_FN = 'samples/python2/data/digits.png'
|
||||
|
||||
def split2d(img, cell_size, flatten=True):
|
||||
h, w = img.shape[:2]
|
||||
sx, sy = cell_size
|
||||
cells = [np.hsplit(row, w//sx) for row in np.vsplit(img, h//sy)]
|
||||
cells = np.array(cells)
|
||||
if flatten:
|
||||
cells = cells.reshape(-1, sy, sx)
|
||||
return cells
|
||||
|
||||
def deskew(img):
|
||||
m = cv2.moments(img)
|
||||
if abs(m['mu02']) < 1e-2:
|
||||
return img.copy()
|
||||
skew = m['mu11']/m['mu02']
|
||||
M = np.float32([[1, skew, -0.5*SZ*skew], [0, 1, 0]])
|
||||
img = cv2.warpAffine(img, M, (SZ, SZ), flags=cv2.WARP_INVERSE_MAP | cv2.INTER_LINEAR)
|
||||
return img
|
||||
|
||||
class StatModel(object):
|
||||
def load(self, fn):
|
||||
self.model.load(fn) # Known bug: https://github.com/Itseez/opencv/issues/4969
|
||||
def save(self, fn):
|
||||
self.model.save(fn)
|
||||
|
||||
class KNearest(StatModel):
|
||||
def __init__(self, k = 3):
|
||||
self.k = k
|
||||
self.model = cv2.KNearest()
|
||||
|
||||
def train(self, samples, responses):
|
||||
self.model.train(samples, responses)
|
||||
|
||||
def predict(self, samples):
|
||||
retval, results, neigh_resp, dists = self.model.find_nearest(samples, self.k)
|
||||
return results.ravel()
|
||||
|
||||
class SVM(StatModel):
|
||||
def __init__(self, C = 1, gamma = 0.5):
|
||||
self.params = dict( kernel_type = cv2.SVM_RBF,
|
||||
svm_type = cv2.SVM_C_SVC,
|
||||
C = C,
|
||||
gamma = gamma )
|
||||
self.model = cv2.SVM()
|
||||
|
||||
def train(self, samples, responses):
|
||||
self.model.train(samples, responses, params = self.params)
|
||||
|
||||
def predict(self, samples):
|
||||
return self.model.predict_all(samples).ravel()
|
||||
|
||||
|
||||
def evaluate_model(model, digits, samples, labels):
|
||||
resp = model.predict(samples)
|
||||
err = (labels != resp).mean()
|
||||
|
||||
confusion = np.zeros((10, 10), np.int32)
|
||||
for i, j in zip(labels, resp):
|
||||
confusion[int(i), int(j)] += 1
|
||||
|
||||
return err, confusion
|
||||
|
||||
def preprocess_simple(digits):
|
||||
return np.float32(digits).reshape(-1, SZ*SZ) / 255.0
|
||||
|
||||
def preprocess_hog(digits):
|
||||
samples = []
|
||||
for img in digits:
|
||||
gx = cv2.Sobel(img, cv2.CV_32F, 1, 0)
|
||||
gy = cv2.Sobel(img, cv2.CV_32F, 0, 1)
|
||||
mag, ang = cv2.cartToPolar(gx, gy)
|
||||
bin_n = 16
|
||||
bin = np.int32(bin_n*ang/(2*np.pi))
|
||||
bin_cells = bin[:10,:10], bin[10:,:10], bin[:10,10:], bin[10:,10:]
|
||||
mag_cells = mag[:10,:10], mag[10:,:10], mag[:10,10:], mag[10:,10:]
|
||||
hists = [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)]
|
||||
hist = np.hstack(hists)
|
||||
|
||||
# transform to Hellinger kernel
|
||||
eps = 1e-7
|
||||
hist /= hist.sum() + eps
|
||||
hist = np.sqrt(hist)
|
||||
hist /= norm(hist) + eps
|
||||
|
||||
samples.append(hist)
|
||||
return np.float32(samples)
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class digits_test(NewOpenCVTests):
|
||||
|
||||
def load_digits(self, fn):
|
||||
digits_img = self.get_sample(fn, 0)
|
||||
digits = split2d(digits_img, (SZ, SZ))
|
||||
labels = np.repeat(np.arange(CLASS_N), len(digits)/CLASS_N)
|
||||
return digits, labels
|
||||
|
||||
def test_digits(self):
|
||||
|
||||
digits, labels = self.load_digits(DIGITS_FN)
|
||||
|
||||
# shuffle digits
|
||||
rand = np.random.RandomState(321)
|
||||
shuffle = rand.permutation(len(digits))
|
||||
digits, labels = digits[shuffle], labels[shuffle]
|
||||
|
||||
digits2 = list(map(deskew, digits))
|
||||
samples = preprocess_hog(digits2)
|
||||
|
||||
train_n = int(0.9*len(samples))
|
||||
digits_train, digits_test = np.split(digits2, [train_n])
|
||||
samples_train, samples_test = np.split(samples, [train_n])
|
||||
labels_train, labels_test = np.split(labels, [train_n])
|
||||
errors = list()
|
||||
confusionMatrixes = list()
|
||||
|
||||
model = KNearest(k=4)
|
||||
model.train(samples_train, labels_train)
|
||||
error, confusion = evaluate_model(model, digits_test, samples_test, labels_test)
|
||||
errors.append(error)
|
||||
confusionMatrixes.append(confusion)
|
||||
|
||||
model = SVM(C=2.67, gamma=5.383)
|
||||
model.train(samples_train, labels_train)
|
||||
error, confusion = evaluate_model(model, digits_test, samples_test, labels_test)
|
||||
errors.append(error)
|
||||
confusionMatrixes.append(confusion)
|
||||
|
||||
eps = 0.001
|
||||
normEps = len(samples_test) * 0.02
|
||||
|
||||
confusionKNN = [[45, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[ 0, 57, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[ 0, 0, 59, 1, 0, 0, 0, 0, 1, 0],
|
||||
[ 0, 0, 0, 43, 0, 0, 0, 1, 0, 0],
|
||||
[ 0, 0, 0, 0, 38, 0, 2, 0, 0, 0],
|
||||
[ 0, 0, 0, 2, 0, 48, 0, 0, 1, 0],
|
||||
[ 0, 1, 0, 0, 0, 0, 51, 0, 0, 0],
|
||||
[ 0, 0, 1, 0, 0, 0, 0, 54, 0, 0],
|
||||
[ 0, 0, 0, 0, 0, 1, 0, 0, 46, 0],
|
||||
[ 1, 1, 0, 1, 1, 0, 0, 0, 2, 42]]
|
||||
|
||||
confusionSVM = [[45, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[ 0, 57, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[ 0, 0, 59, 2, 0, 0, 0, 0, 0, 0],
|
||||
[ 0, 0, 0, 43, 0, 0, 0, 1, 0, 0],
|
||||
[ 0, 0, 0, 0, 40, 0, 0, 0, 0, 0],
|
||||
[ 0, 0, 0, 1, 0, 50, 0, 0, 0, 0],
|
||||
[ 0, 0, 0, 0, 1, 0, 51, 0, 0, 0],
|
||||
[ 0, 0, 1, 0, 0, 0, 0, 54, 0, 0],
|
||||
[ 0, 0, 0, 0, 0, 0, 0, 0, 47, 0],
|
||||
[ 0, 1, 0, 1, 0, 0, 0, 0, 1, 45]]
|
||||
|
||||
self.assertLess(cv2.norm(confusionMatrixes[0] - confusionKNN, cv2.NORM_L1), normEps)
|
||||
self.assertLess(cv2.norm(confusionMatrixes[1] - confusionSVM, cv2.NORM_L1), normEps)
|
||||
|
||||
self.assertLess(errors[0] - 0.034, eps)
|
||||
self.assertLess(errors[1] - 0.018, eps)
|
||||
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
face detection using haar cascades
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
def detect(img, cascade):
|
||||
rects = cascade.detectMultiScale(img, scaleFactor=1.3, minNeighbors=2, minSize=(30, 30),
|
||||
flags=cv2.CASCADE_SCALE_IMAGE)
|
||||
if len(rects) == 0:
|
||||
return []
|
||||
rects[:,2:] += rects[:,:2]
|
||||
return rects
|
||||
|
||||
from tests_common import NewOpenCVTests, intersectionRate
|
||||
|
||||
class facedetect_test(NewOpenCVTests):
|
||||
|
||||
def test_facedetect(self):
|
||||
import sys, getopt
|
||||
|
||||
cascade_fn = self.repoPath + '/data/haarcascades/haarcascade_frontalface_alt.xml'
|
||||
nested_fn = self.repoPath + '/data/haarcascades/haarcascade_eye.xml'
|
||||
|
||||
cascade = cv2.CascadeClassifier(cascade_fn)
|
||||
nested = cv2.CascadeClassifier(nested_fn)
|
||||
|
||||
samples = ['samples/c/lena.jpg', 'cv/cascadeandhog/images/mona-lisa.png']
|
||||
|
||||
faces = []
|
||||
eyes = []
|
||||
|
||||
testFaces = [
|
||||
#lena
|
||||
[[218, 200, 389, 371],
|
||||
[ 244, 240, 294, 290],
|
||||
[ 309, 246, 352, 289]],
|
||||
|
||||
#lisa
|
||||
[[167, 119, 307, 259],
|
||||
[188, 153, 229, 194],
|
||||
[236, 153, 277, 194]]
|
||||
]
|
||||
|
||||
for sample in samples:
|
||||
|
||||
img = self.get_sample( sample)
|
||||
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||
gray = cv2.GaussianBlur(gray, (5, 5), 5.1)
|
||||
|
||||
rects = detect(gray, cascade)
|
||||
faces.append(rects)
|
||||
|
||||
if not nested.empty():
|
||||
for x1, y1, x2, y2 in rects:
|
||||
roi = gray[y1:y2, x1:x2]
|
||||
subrects = detect(roi.copy(), nested)
|
||||
|
||||
for rect in subrects:
|
||||
rect[0] += x1
|
||||
rect[2] += x1
|
||||
rect[1] += y1
|
||||
rect[3] += y1
|
||||
|
||||
eyes.append(subrects)
|
||||
|
||||
faces_matches = 0
|
||||
eyes_matches = 0
|
||||
|
||||
eps = 0.8
|
||||
|
||||
for i in range(len(faces)):
|
||||
for j in range(len(testFaces)):
|
||||
if intersectionRate(faces[i][0], testFaces[j][0]) > eps:
|
||||
faces_matches += 1
|
||||
#check eyes
|
||||
if len(eyes[i]) == 2:
|
||||
if intersectionRate(eyes[i][0], testFaces[j][1]) > eps and intersectionRate(eyes[i][1] , testFaces[j][2]) > eps:
|
||||
eyes_matches += 1
|
||||
elif intersectionRate(eyes[i][1], testFaces[j][1]) > eps and intersectionRate(eyes[i][0], testFaces[j][2]) > eps:
|
||||
eyes_matches += 1
|
||||
|
||||
self.assertEqual(faces_matches, 2)
|
||||
self.assertEqual(eyes_matches, 2)
|
||||
@@ -0,0 +1,160 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
Feature homography
|
||||
==================
|
||||
|
||||
Example of using features2d framework for interactive video homography matching.
|
||||
ORB features and FLANN matcher are used. The actual tracking is implemented by
|
||||
PlaneTracker class in plane_tracker.py
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
import sys
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
if PY3:
|
||||
xrange = range
|
||||
|
||||
# local modules
|
||||
from tst_scene_render import TestSceneRender
|
||||
|
||||
def intersectionRate(s1, s2):
|
||||
|
||||
x1, y1, x2, y2 = s1
|
||||
s1 = np.array([[x1, y1], [x2,y1], [x2, y2], [x1, y2]])
|
||||
|
||||
area, intersection = cv2.intersectConvexConvex(s1, np.array(s2))
|
||||
return 2 * area / (cv2.contourArea(s1) + cv2.contourArea(np.array(s2)))
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class feature_homography_test(NewOpenCVTests):
|
||||
|
||||
render = None
|
||||
tracker = None
|
||||
framesCounter = 0
|
||||
frame = None
|
||||
|
||||
def test_feature_homography(self):
|
||||
|
||||
self.render = TestSceneRender(self.get_sample('samples/python2/data/graf1.png'),
|
||||
self.get_sample('samples/c/box.png'), noise = 0.4, speed = 0.5)
|
||||
self.frame = self.render.getNextFrame()
|
||||
self.tracker = PlaneTracker()
|
||||
self.tracker.clear()
|
||||
self.tracker.add_target(self.frame, self.render.getCurrentRect())
|
||||
|
||||
while self.framesCounter < 100:
|
||||
self.framesCounter += 1
|
||||
tracked = self.tracker.track(self.frame)
|
||||
if len(tracked) > 0:
|
||||
tracked = tracked[0]
|
||||
self.assertGreater(intersectionRate(self.render.getCurrentRect(), np.int32(tracked.quad)), 0.6)
|
||||
else:
|
||||
self.assertEqual(0, 1, 'Tracking error')
|
||||
self.frame = self.render.getNextFrame()
|
||||
|
||||
|
||||
# built-in modules
|
||||
from collections import namedtuple
|
||||
|
||||
FLANN_INDEX_KDTREE = 1
|
||||
FLANN_INDEX_LSH = 6
|
||||
flann_params= dict(algorithm = FLANN_INDEX_LSH,
|
||||
table_number = 6, # 12
|
||||
key_size = 12, # 20
|
||||
multi_probe_level = 1) #2
|
||||
|
||||
MIN_MATCH_COUNT = 10
|
||||
|
||||
'''
|
||||
image - image to track
|
||||
rect - tracked rectangle (x1, y1, x2, y2)
|
||||
keypoints - keypoints detected inside rect
|
||||
descrs - their descriptors
|
||||
data - some user-provided data
|
||||
'''
|
||||
PlanarTarget = namedtuple('PlaneTarget', 'image, rect, keypoints, descrs, data')
|
||||
|
||||
'''
|
||||
target - reference to PlanarTarget
|
||||
p0 - matched points coords in target image
|
||||
p1 - matched points coords in input frame
|
||||
H - homography matrix from p0 to p1
|
||||
quad - target bounary quad in input frame
|
||||
'''
|
||||
TrackedTarget = namedtuple('TrackedTarget', 'target, p0, p1, H, quad')
|
||||
|
||||
class PlaneTracker:
|
||||
def __init__(self):
|
||||
self.detector = cv2.ORB( nfeatures = 1000 )
|
||||
self.matcher = cv2.FlannBasedMatcher(flann_params, {}) # bug : need to pass empty dict (#1329)
|
||||
self.targets = []
|
||||
self.frame_points = []
|
||||
|
||||
def add_target(self, image, rect, data=None):
|
||||
'''Add a new tracking target.'''
|
||||
x0, y0, x1, y1 = rect
|
||||
raw_points, raw_descrs = self.detect_features(image)
|
||||
points, descs = [], []
|
||||
for kp, desc in zip(raw_points, raw_descrs):
|
||||
x, y = kp.pt
|
||||
if x0 <= x <= x1 and y0 <= y <= y1:
|
||||
points.append(kp)
|
||||
descs.append(desc)
|
||||
descs = np.uint8(descs)
|
||||
self.matcher.add([descs])
|
||||
target = PlanarTarget(image = image, rect=rect, keypoints = points, descrs=descs, data=data)
|
||||
self.targets.append(target)
|
||||
|
||||
def clear(self):
|
||||
'''Remove all targets'''
|
||||
self.targets = []
|
||||
self.matcher.clear()
|
||||
|
||||
def track(self, frame):
|
||||
'''Returns a list of detected TrackedTarget objects'''
|
||||
self.frame_points, frame_descrs = self.detect_features(frame)
|
||||
if len(self.frame_points) < MIN_MATCH_COUNT:
|
||||
return []
|
||||
matches = self.matcher.knnMatch(frame_descrs, k = 2)
|
||||
matches = [m[0] for m in matches if len(m) == 2 and m[0].distance < m[1].distance * 0.75]
|
||||
if len(matches) < MIN_MATCH_COUNT:
|
||||
return []
|
||||
matches_by_id = [[] for _ in xrange(len(self.targets))]
|
||||
for m in matches:
|
||||
matches_by_id[m.imgIdx].append(m)
|
||||
tracked = []
|
||||
for imgIdx, matches in enumerate(matches_by_id):
|
||||
if len(matches) < MIN_MATCH_COUNT:
|
||||
continue
|
||||
target = self.targets[imgIdx]
|
||||
p0 = [target.keypoints[m.trainIdx].pt for m in matches]
|
||||
p1 = [self.frame_points[m.queryIdx].pt for m in matches]
|
||||
p0, p1 = np.float32((p0, p1))
|
||||
H, status = cv2.findHomography(p0, p1, cv2.RANSAC, 3.0)
|
||||
status = status.ravel() != 0
|
||||
if status.sum() < MIN_MATCH_COUNT:
|
||||
continue
|
||||
p0, p1 = p0[status], p1[status]
|
||||
|
||||
x0, y0, x1, y1 = target.rect
|
||||
quad = np.float32([[x0, y0], [x1, y0], [x1, y1], [x0, y1]])
|
||||
quad = cv2.perspectiveTransform(quad.reshape(1, -1, 2), H).reshape(-1, 2)
|
||||
|
||||
track = TrackedTarget(target=target, p0=p0, p1=p1, H=H, quad=quad)
|
||||
tracked.append(track)
|
||||
tracked.sort(key = lambda t: len(t.p0), reverse=True)
|
||||
return tracked
|
||||
|
||||
def detect_features(self, frame):
|
||||
'''detect_features(self, frame) -> keypoints, descrs'''
|
||||
keypoints, descrs = self.detector.detectAndCompute(frame, None)
|
||||
if descrs is None: # detectAndCompute returns descs=None if not keypoints found
|
||||
descrs = []
|
||||
return keypoints, descrs
|
||||
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
Robust line fitting.
|
||||
==================
|
||||
|
||||
Example of using cv2.fitLine function for fitting line
|
||||
to points in presence of outliers.
|
||||
|
||||
Switch through different M-estimator functions and see,
|
||||
how well the robust functions fit the line even
|
||||
in case of ~50% of outliers.
|
||||
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
w, h = 512, 256
|
||||
|
||||
def toint(p):
|
||||
return tuple(map(int, p))
|
||||
|
||||
def sample_line(p1, p2, n, noise=0.0):
|
||||
np.random.seed(10)
|
||||
p1 = np.float32(p1)
|
||||
t = np.random.rand(n,1)
|
||||
return p1 + (p2-p1)*t + np.random.normal(size=(n, 2))*noise
|
||||
|
||||
dist_func_names = ['CV_DIST_L2', 'CV_DIST_L1', 'CV_DIST_L12', 'CV_DIST_FAIR', 'CV_DIST_WELSCH', 'CV_DIST_HUBER']
|
||||
|
||||
class fitline_test(NewOpenCVTests):
|
||||
|
||||
def test_fitline(self):
|
||||
|
||||
noise = 5
|
||||
n = 200
|
||||
r = 5 / 100.0
|
||||
outn = int(n*r)
|
||||
|
||||
p0, p1 = (90, 80), (w-90, h-80)
|
||||
line_points = sample_line(p0, p1, n-outn, noise)
|
||||
outliers = np.random.rand(outn, 2) * (w, h)
|
||||
points = np.vstack([line_points, outliers])
|
||||
|
||||
lines = []
|
||||
|
||||
for name in dist_func_names:
|
||||
func = getattr(cv2.cv, name)
|
||||
vx, vy, cx, cy = cv2.fitLine(np.float32(points), func, 0, 0.01, 0.01)
|
||||
line = [float(vx), float(vy), float(cx), float(cy)]
|
||||
lines.append(line)
|
||||
|
||||
eps = 0.05
|
||||
|
||||
refVec = (np.float32(p1) - p0) / cv2.norm(np.float32(p1) - p0)
|
||||
|
||||
for i in range(len(lines)):
|
||||
self.assertLessEqual(cv2.norm(refVec - lines[i][0:2], cv2.NORM_L2), eps)
|
||||
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
if PY3:
|
||||
xrange = range
|
||||
|
||||
import numpy as np
|
||||
from numpy import random
|
||||
import cv2
|
||||
|
||||
def make_gaussians(cluster_n, img_size):
|
||||
points = []
|
||||
ref_distrs = []
|
||||
for i in xrange(cluster_n):
|
||||
mean = (0.1 + 0.8*random.rand(2)) * img_size
|
||||
a = (random.rand(2, 2)-0.5)*img_size*0.1
|
||||
cov = np.dot(a.T, a) + img_size*0.05*np.eye(2)
|
||||
n = 100 + random.randint(900)
|
||||
pts = random.multivariate_normal(mean, cov, n)
|
||||
points.append( pts )
|
||||
ref_distrs.append( (mean, cov) )
|
||||
points = np.float32( np.vstack(points) )
|
||||
return points, ref_distrs
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class gaussian_mix_test(NewOpenCVTests):
|
||||
|
||||
def test_gaussian_mix(self):
|
||||
|
||||
np.random.seed(10)
|
||||
cluster_n = 5
|
||||
img_size = 512
|
||||
|
||||
points, ref_distrs = make_gaussians(cluster_n, img_size)
|
||||
|
||||
em = cv2.EM(cluster_n,cv2.EM_COV_MAT_GENERIC)
|
||||
em.train(points)
|
||||
means = em.getMat("means")
|
||||
covs = em.getMatVector("covs") # Known bug: https://github.com/Itseez/opencv/pull/4232
|
||||
found_distrs = zip(means, covs)
|
||||
|
||||
matches_count = 0
|
||||
|
||||
meanEps = 0.05
|
||||
covEps = 0.1
|
||||
|
||||
for i in range(cluster_n):
|
||||
for j in range(cluster_n):
|
||||
if (cv2.norm(means[i] - ref_distrs[j][0], cv2.NORM_L2) / cv2.norm(ref_distrs[j][0], cv2.NORM_L2) < meanEps and
|
||||
cv2.norm(covs[i] - ref_distrs[j][1], cv2.NORM_L2) / cv2.norm(ref_distrs[j][1], cv2.NORM_L2) < covEps):
|
||||
matches_count += 1
|
||||
|
||||
self.assertEqual(matches_count, cluster_n)
|
||||
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
===============================================================================
|
||||
Interactive Image Segmentation using GrabCut algorithm.
|
||||
===============================================================================
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
import sys
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class grabcut_test(NewOpenCVTests):
|
||||
|
||||
def verify(self, mask, exp):
|
||||
|
||||
maxDiffRatio = 0.02
|
||||
expArea = np.count_nonzero(exp)
|
||||
nonIntersectArea = np.count_nonzero(mask != exp)
|
||||
curRatio = float(nonIntersectArea) / expArea
|
||||
return curRatio < maxDiffRatio
|
||||
|
||||
def scaleMask(self, mask):
|
||||
|
||||
return np.where((mask==cv2.GC_FGD) + (mask==cv2.GC_PR_FGD),255,0).astype('uint8')
|
||||
|
||||
def test_grabcut(self):
|
||||
|
||||
img = self.get_sample('cv/shared/airplane.png')
|
||||
mask_prob = self.get_sample("cv/grabcut/mask_probpy.png", 0)
|
||||
exp_mask1 = self.get_sample("cv/grabcut/exp_mask1py.png", 0)
|
||||
exp_mask2 = self.get_sample("cv/grabcut/exp_mask2py.png", 0)
|
||||
|
||||
if img is None:
|
||||
self.assertTrue(False, 'Missing test data')
|
||||
|
||||
rect = (24, 126, 459, 168)
|
||||
mask = np.zeros(img.shape[:2], dtype = np.uint8)
|
||||
bgdModel = np.zeros((1,65),np.float64)
|
||||
fgdModel = np.zeros((1,65),np.float64)
|
||||
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 0, cv2.GC_INIT_WITH_RECT)
|
||||
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 2, cv2.GC_EVAL)
|
||||
|
||||
if mask_prob is None:
|
||||
mask_prob = mask.copy()
|
||||
cv2.imwrite(self.extraTestDataPath + '/cv/grabcut/mask_probpy.png', mask_prob)
|
||||
if exp_mask1 is None:
|
||||
exp_mask1 = self.scaleMask(mask)
|
||||
cv2.imwrite(self.extraTestDataPath + '/cv/grabcut/exp_mask1py.png', exp_mask1)
|
||||
|
||||
self.assertEqual(self.verify(self.scaleMask(mask), exp_mask1), True)
|
||||
|
||||
mask = mask_prob
|
||||
bgdModel = np.zeros((1,65),np.float64)
|
||||
fgdModel = np.zeros((1,65),np.float64)
|
||||
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 0, cv2.GC_INIT_WITH_MASK)
|
||||
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 1, cv2.GC_EVAL)
|
||||
|
||||
if exp_mask2 is None:
|
||||
exp_mask2 = self.scaleMask(mask)
|
||||
cv2.imwrite(self.extraTestDataPath + '/cv/grabcut/exp_mask2py.png', exp_mask2)
|
||||
|
||||
self.assertEqual(self.verify(self.scaleMask(mask), exp_mask2), True)
|
||||
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
'''
|
||||
This example illustrates how to use cv2.HoughCircles() function.
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
import sys
|
||||
from numpy import pi, sin, cos
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
def circleApproximation(circle):
|
||||
|
||||
nPoints = 30
|
||||
phi = 0
|
||||
dPhi = 2*pi / nPoints
|
||||
contour = []
|
||||
for i in range(nPoints):
|
||||
contour.append(([circle[0] + circle[2]*cos(i*dPhi),
|
||||
circle[1] + circle[2]*sin(i*dPhi)]))
|
||||
|
||||
return np.array(contour).astype(int)
|
||||
|
||||
def convContoursIntersectiponRate(c1, c2):
|
||||
|
||||
s1 = cv2.contourArea(c1)
|
||||
s2 = cv2.contourArea(c2)
|
||||
|
||||
s, _ = cv2.intersectConvexConvex(c1, c2)
|
||||
|
||||
return 2*s/(s1+s2)
|
||||
|
||||
class houghcircles_test(NewOpenCVTests):
|
||||
|
||||
def test_houghcircles(self):
|
||||
|
||||
fn = "samples/cpp/board.jpg"
|
||||
|
||||
src = self.get_sample(fn, 1)
|
||||
img = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
|
||||
img = cv2.medianBlur(img, 5)
|
||||
|
||||
circles = cv2.HoughCircles(img, cv2.cv.CV_HOUGH_GRADIENT, 1, 10, np.array([]), 100, 30, 1, 30)[0]
|
||||
|
||||
testCircles = [[38, 181, 17.6],
|
||||
[99.7, 166, 13.12],
|
||||
[142.7, 160, 13.52],
|
||||
[223.6, 110, 8.62],
|
||||
[79.1, 206.7, 8.62],
|
||||
[47.5, 351.6, 11.64],
|
||||
[189.5, 354.4, 11.64],
|
||||
[189.8, 298.9, 10.64],
|
||||
[189.5, 252.4, 14.62],
|
||||
[252.5, 393.4, 15.62],
|
||||
[602.9, 467.5, 11.42],
|
||||
[222, 210.4, 9.12],
|
||||
[263.1, 216.7, 9.12],
|
||||
[359.8, 222.6, 9.12],
|
||||
[518.9, 120.9, 9.12],
|
||||
[413.8, 113.4, 9.12],
|
||||
[489, 127.2, 9.12],
|
||||
[448.4, 121.3, 9.12],
|
||||
[384.6, 128.9, 8.62]]
|
||||
|
||||
matches_counter = 0
|
||||
|
||||
for i in range(len(testCircles)):
|
||||
for j in range(len(circles)):
|
||||
|
||||
tstCircle = circleApproximation(testCircles[i])
|
||||
circle = circleApproximation(circles[j])
|
||||
if convContoursIntersectiponRate(tstCircle, circle) > 0.6:
|
||||
matches_counter += 1
|
||||
|
||||
self.assertGreater(float(matches_counter) / len(testCircles), .5)
|
||||
self.assertLess(float(len(circles) - matches_counter) / len(circles), .75)
|
||||
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
'''
|
||||
This example illustrates how to use Hough Transform to find lines
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
import sys
|
||||
import math
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
def linesDiff(line1, line2):
|
||||
|
||||
norm1 = cv2.norm(line1 - line2, cv2.NORM_L2)
|
||||
line3 = line1[2:4] + line1[0:2]
|
||||
norm2 = cv2.norm(line3 - line2, cv2.NORM_L2)
|
||||
|
||||
return min(norm1, norm2)
|
||||
|
||||
class houghlines_test(NewOpenCVTests):
|
||||
|
||||
def test_houghlines(self):
|
||||
|
||||
fn = "/samples/cpp/pic1.png"
|
||||
|
||||
src = self.get_sample(fn)
|
||||
dst = cv2.Canny(src, 50, 200)
|
||||
|
||||
lines = cv2.HoughLinesP(dst, 1, math.pi/180.0, 40, np.array([]), 50, 10)[0,:,:]
|
||||
|
||||
eps = 5
|
||||
testLines = [
|
||||
#rect1
|
||||
[ 232, 25, 43, 25],
|
||||
[ 43, 129, 232, 129],
|
||||
[ 43, 129, 43, 25],
|
||||
[232, 129, 232, 25],
|
||||
#rect2
|
||||
[251, 86, 314, 183],
|
||||
[252, 86, 323, 40],
|
||||
[315, 183, 386, 137],
|
||||
[324, 40, 386, 136],
|
||||
#triangle
|
||||
[245, 205, 377, 205],
|
||||
[244, 206, 305, 278],
|
||||
[306, 279, 377, 205],
|
||||
#rect3
|
||||
[153, 177, 196, 177],
|
||||
[153, 277, 153, 179],
|
||||
[153, 277, 196, 277],
|
||||
[196, 177, 196, 277]]
|
||||
|
||||
matches_counter = 0
|
||||
|
||||
for i in range(len(testLines)):
|
||||
for j in range(len(lines)):
|
||||
if linesDiff(testLines[i], lines[j]) < eps:
|
||||
matches_counter += 1
|
||||
|
||||
self.assertGreater(float(matches_counter) / len(testLines), .7)
|
||||
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
K-means clusterization test
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
from numpy import random
|
||||
import sys
|
||||
PY3 = sys.version_info[0] == 3
|
||||
if PY3:
|
||||
xrange = range
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
def make_gaussians(cluster_n, img_size):
|
||||
points = []
|
||||
ref_distrs = []
|
||||
sizes = []
|
||||
for i in xrange(cluster_n):
|
||||
mean = (0.1 + 0.8*random.rand(2)) * img_size
|
||||
a = (random.rand(2, 2)-0.5)*img_size*0.1
|
||||
cov = np.dot(a.T, a) + img_size*0.05*np.eye(2)
|
||||
n = 100 + random.randint(900)
|
||||
pts = random.multivariate_normal(mean, cov, n)
|
||||
points.append( pts )
|
||||
ref_distrs.append( (mean, cov) )
|
||||
sizes.append(n)
|
||||
points = np.float32( np.vstack(points) )
|
||||
return points, ref_distrs, sizes
|
||||
|
||||
def getMainLabelConfidence(labels, nLabels):
|
||||
|
||||
n = len(labels)
|
||||
labelsDict = dict.fromkeys(range(nLabels), 0)
|
||||
labelsConfDict = dict.fromkeys(range(nLabels))
|
||||
|
||||
for i in range(n):
|
||||
labelsDict[labels[i][0]] += 1
|
||||
|
||||
for i in range(nLabels):
|
||||
labelsConfDict[i] = float(labelsDict[i]) / n
|
||||
|
||||
return max(labelsConfDict.values())
|
||||
|
||||
class kmeans_test(NewOpenCVTests):
|
||||
|
||||
def test_kmeans(self):
|
||||
|
||||
np.random.seed(10)
|
||||
|
||||
cluster_n = 5
|
||||
img_size = 512
|
||||
|
||||
points, _, clusterSizes = make_gaussians(cluster_n, img_size)
|
||||
|
||||
term_crit = (cv2.TERM_CRITERIA_EPS, 30, 0.1)
|
||||
ret, labels, centers = cv2.kmeans(points, cluster_n, term_crit, 10, 0)
|
||||
|
||||
self.assertEqual(len(centers), cluster_n)
|
||||
|
||||
offset = 0
|
||||
for i in range(cluster_n):
|
||||
confidence = getMainLabelConfidence(labels[offset : (offset + clusterSizes[i])], cluster_n)
|
||||
offset += clusterSizes[i]
|
||||
self.assertGreater(confidence, 0.9)
|
||||
@@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
The sample demonstrates how to train Random Trees classifier
|
||||
(or Boosting classifier, or MLP, or Knearest, or Support Vector Machines) using the provided dataset.
|
||||
|
||||
We use the sample database letter-recognition.data
|
||||
from UCI Repository, here is the link:
|
||||
|
||||
Newman, D.J. & Hettich, S. & Blake, C.L. & Merz, C.J. (1998).
|
||||
UCI Repository of machine learning databases
|
||||
[http://www.ics.uci.edu/~mlearn/MLRepository.html].
|
||||
Irvine, CA: University of California, Department of Information and Computer Science.
|
||||
|
||||
The dataset consists of 20000 feature vectors along with the
|
||||
responses - capital latin letters A..Z.
|
||||
The first 10000 samples are used for training
|
||||
and the remaining 10000 - to test the classifier.
|
||||
======================================================
|
||||
Models: RTrees, KNearest, Boost, SVM, MLP
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
def load_base(fn):
|
||||
a = np.loadtxt(fn, np.float32, delimiter=',', converters={ 0 : lambda ch : ord(ch)-ord('A') })
|
||||
samples, responses = a[:,1:], a[:,0]
|
||||
return samples, responses
|
||||
|
||||
class LetterStatModel(object):
|
||||
class_n = 26
|
||||
train_ratio = 0.5
|
||||
|
||||
def load(self, fn):
|
||||
self.model.load(fn)
|
||||
def save(self, fn):
|
||||
self.model.save(fn)
|
||||
|
||||
def unroll_samples(self, samples):
|
||||
sample_n, var_n = samples.shape
|
||||
new_samples = np.zeros((sample_n * self.class_n, var_n+1), np.float32)
|
||||
new_samples[:,:-1] = np.repeat(samples, self.class_n, axis=0)
|
||||
new_samples[:,-1] = np.tile(np.arange(self.class_n), sample_n)
|
||||
return new_samples
|
||||
|
||||
def unroll_responses(self, responses):
|
||||
sample_n = len(responses)
|
||||
new_responses = np.zeros(sample_n*self.class_n, np.int32)
|
||||
resp_idx = np.int32( responses + np.arange(sample_n)*self.class_n )
|
||||
new_responses[resp_idx] = 1
|
||||
return new_responses
|
||||
|
||||
class RTrees(LetterStatModel):
|
||||
def __init__(self):
|
||||
self.model = cv2.RTrees()
|
||||
|
||||
def train(self, samples, responses):
|
||||
sample_n, var_n = samples.shape
|
||||
params = dict(max_depth=20 )
|
||||
self.model.train(samples, cv2.CV_ROW_SAMPLE, responses.astype(int), params = params)
|
||||
|
||||
def predict(self, samples):
|
||||
return np.float32( [self.model.predict(s) for s in samples] )
|
||||
|
||||
|
||||
class KNearest(LetterStatModel):
|
||||
def __init__(self):
|
||||
self.model = cv2.KNearest()
|
||||
|
||||
def train(self, samples, responses):
|
||||
self.model.train(samples, responses)
|
||||
|
||||
def predict(self, samples):
|
||||
retval, results, neigh_resp, dists = self.model.find_nearest(samples, k = 10)
|
||||
return results.ravel()
|
||||
|
||||
|
||||
class Boost(LetterStatModel):
|
||||
def __init__(self):
|
||||
self.model = cv2.Boost()
|
||||
|
||||
def train(self, samples, responses):
|
||||
sample_n, var_n = samples.shape
|
||||
new_samples = self.unroll_samples(samples)
|
||||
new_responses = self.unroll_responses(responses)
|
||||
var_types = np.array([cv2.CV_VAR_NUMERICAL] * var_n + [cv2.CV_VAR_CATEGORICAL, cv2.CV_VAR_CATEGORICAL], np.uint8)
|
||||
params = dict(max_depth=10, weak_count=15)
|
||||
self.model.train(new_samples, cv2.CV_ROW_SAMPLE, new_responses.astype(int), varType = var_types, params=params)
|
||||
|
||||
def predict(self, samples):
|
||||
new_samples = self.unroll_samples(samples)
|
||||
pred = np.array( [self.model.predict(s) for s in new_samples] )
|
||||
pred = pred.reshape(-1, self.class_n).argmax(1)
|
||||
return pred
|
||||
|
||||
|
||||
class SVM(LetterStatModel):
|
||||
def __init__(self):
|
||||
self.model = cv2.SVM()
|
||||
|
||||
def train(self, samples, responses):
|
||||
params = dict( kernel_type = cv2.SVM_RBF,
|
||||
svm_type = cv2.SVM_C_SVC,
|
||||
C = 1,
|
||||
gamma = .1 )
|
||||
self.model.train(samples, responses.astype(int), params = params)
|
||||
|
||||
def predict(self, samples):
|
||||
return self.model.predict_all(samples).ravel()
|
||||
|
||||
|
||||
class MLP(LetterStatModel):
|
||||
def __init__(self):
|
||||
self.model = cv2.ANN_MLP()
|
||||
|
||||
def train(self, samples, responses):
|
||||
sample_n, var_n = samples.shape
|
||||
new_responses = self.unroll_responses(responses).reshape(-1, self.class_n)
|
||||
layer_sizes = np.int32([var_n, 100, 100, self.class_n])
|
||||
|
||||
self.model.create(layer_sizes, cv2.ANN_MLP_SIGMOID_SYM, 2, 1)
|
||||
params = dict( train_method = cv2.ANN_MLP_TRAIN_PARAMS_BACKPROP,
|
||||
bp_moment_scale = 0.0,
|
||||
bp_dw_scale = 0.001,
|
||||
term_crit = (cv2.TERM_CRITERIA_COUNT, 20, 0.01) )
|
||||
self.model.train(samples, np.float32(new_responses), None, params = params)
|
||||
|
||||
def predict(self, samples):
|
||||
ret, resp = self.model.predict(samples)
|
||||
return resp.argmax(-1)
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class letter_recog_test(NewOpenCVTests):
|
||||
|
||||
def test_letter_recog(self):
|
||||
|
||||
eps = 0.01
|
||||
|
||||
models = [RTrees, KNearest, Boost, SVM, MLP]
|
||||
models = dict( [(cls.__name__.lower(), cls) for cls in models] )
|
||||
testErrors = {RTrees: (98.930000, 92.390000), KNearest: (94.960000, 92.010000),
|
||||
Boost: (85.970000, 74.920000), SVM: (99.780000, 95.680000), MLP: (90.060000, 87.410000)}
|
||||
|
||||
for model in models:
|
||||
Model = models[model]
|
||||
classifier = Model()
|
||||
|
||||
samples, responses = load_base(self.repoPath + '/samples/cpp/letter-recognition.data')
|
||||
train_n = int(len(samples)*classifier.train_ratio)
|
||||
|
||||
classifier.train(samples[:train_n], responses[:train_n])
|
||||
train_rate = np.mean(classifier.predict(samples[:train_n]) == responses[:train_n].astype(int))
|
||||
test_rate = np.mean(classifier.predict(samples[train_n:]) == responses[train_n:].astype(int))
|
||||
|
||||
self.assertLess(train_rate - testErrors[Model][0], eps)
|
||||
self.assertLess(test_rate - testErrors[Model][1], eps)
|
||||
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
Lucas-Kanade homography tracker test
|
||||
===============================
|
||||
Uses goodFeaturesToTrack for track initialization and back-tracking for match verification
|
||||
between frames. Finds homography between reference and current views.
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
#local modules
|
||||
from tst_scene_render import TestSceneRender
|
||||
from tests_common import NewOpenCVTests, isPointInRect
|
||||
|
||||
lk_params = dict( winSize = (19, 19),
|
||||
maxLevel = 2,
|
||||
criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
|
||||
|
||||
feature_params = dict( maxCorners = 1000,
|
||||
qualityLevel = 0.01,
|
||||
minDistance = 8,
|
||||
blockSize = 19 )
|
||||
|
||||
def checkedTrace(img0, img1, p0, back_threshold = 1.0):
|
||||
p1, st, err = cv2.calcOpticalFlowPyrLK(img0, img1, p0, None, **lk_params)
|
||||
p0r, st, err = cv2.calcOpticalFlowPyrLK(img1, img0, p1, None, **lk_params)
|
||||
d = abs(p0-p0r).reshape(-1, 2).max(-1)
|
||||
status = d < back_threshold
|
||||
return p1, status
|
||||
|
||||
class lk_homography_test(NewOpenCVTests):
|
||||
|
||||
render = None
|
||||
framesCounter = 0
|
||||
frame = frame0 = None
|
||||
p0 = None
|
||||
p1 = None
|
||||
gray0 = gray1 = None
|
||||
numFeaturesInRectOnStart = 0
|
||||
|
||||
def test_lk_homography(self):
|
||||
self.render = TestSceneRender(self.get_sample('samples/python2/data/graf1.png'),
|
||||
self.get_sample('samples/c/box.png'), noise = 0.1, speed = 1.0)
|
||||
|
||||
frame = self.render.getNextFrame()
|
||||
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
||||
self.frame0 = frame.copy()
|
||||
self.p0 = cv2.goodFeaturesToTrack(frame_gray, **feature_params)
|
||||
|
||||
isForegroundHomographyFound = False
|
||||
|
||||
if self.p0 is not None:
|
||||
self.p1 = self.p0
|
||||
self.gray0 = frame_gray
|
||||
self.gray1 = frame_gray
|
||||
currRect = self.render.getCurrentRect()
|
||||
for (x,y) in self.p0[:,0]:
|
||||
if isPointInRect((x,y), currRect):
|
||||
self.numFeaturesInRectOnStart += 1
|
||||
|
||||
while self.framesCounter < 200:
|
||||
self.framesCounter += 1
|
||||
frame = self.render.getNextFrame()
|
||||
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
||||
if self.p0 is not None:
|
||||
p2, trace_status = checkedTrace(self.gray1, frame_gray, self.p1)
|
||||
|
||||
self.p1 = p2[trace_status].copy()
|
||||
self.p0 = self.p0[trace_status].copy()
|
||||
self.gray1 = frame_gray
|
||||
|
||||
if len(self.p0) < 4:
|
||||
self.p0 = None
|
||||
continue
|
||||
H, status = cv2.findHomography(self.p0, self.p1, cv2.RANSAC, 5.0)
|
||||
|
||||
goodPointsInRect = 0
|
||||
goodPointsOutsideRect = 0
|
||||
for (x0, y0), (x1, y1), good in zip(self.p0[:,0], self.p1[:,0], status[:,0]):
|
||||
if good:
|
||||
if isPointInRect((x1,y1), self.render.getCurrentRect()):
|
||||
goodPointsInRect += 1
|
||||
else: goodPointsOutsideRect += 1
|
||||
|
||||
if goodPointsOutsideRect < goodPointsInRect:
|
||||
isForegroundHomographyFound = True
|
||||
self.assertGreater(float(goodPointsInRect) / (self.numFeaturesInRectOnStart + 1), 0.6)
|
||||
else:
|
||||
p = cv2.goodFeaturesToTrack(frame_gray, **feature_params)
|
||||
|
||||
self.assertEqual(isForegroundHomographyFound, True)
|
||||
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
Lucas-Kanade tracker
|
||||
====================
|
||||
|
||||
Lucas-Kanade sparse optical flow demo. Uses goodFeaturesToTrack
|
||||
for track initialization and back-tracking for match verification
|
||||
between frames.
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
#local modules
|
||||
from tst_scene_render import TestSceneRender
|
||||
from tests_common import NewOpenCVTests, intersectionRate, isPointInRect
|
||||
|
||||
lk_params = dict( winSize = (15, 15),
|
||||
maxLevel = 2,
|
||||
criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
|
||||
|
||||
feature_params = dict( maxCorners = 500,
|
||||
qualityLevel = 0.3,
|
||||
minDistance = 7,
|
||||
blockSize = 7 )
|
||||
|
||||
def getRectFromPoints(points):
|
||||
|
||||
distances = []
|
||||
for point in points:
|
||||
distances.append(cv2.norm(point, cv2.NORM_L2))
|
||||
|
||||
x0, y0 = points[np.argmin(distances)]
|
||||
x1, y1 = points[np.argmax(distances)]
|
||||
|
||||
return np.array([x0, y0, x1, y1])
|
||||
|
||||
|
||||
class lk_track_test(NewOpenCVTests):
|
||||
|
||||
track_len = 10
|
||||
detect_interval = 5
|
||||
tracks = []
|
||||
frame_idx = 0
|
||||
render = None
|
||||
|
||||
def test_lk_track(self):
|
||||
|
||||
self.render = TestSceneRender(self.get_sample('samples/python2/data/graf1.png'), self.get_sample('samples/c/box.png'))
|
||||
self.runTracker()
|
||||
|
||||
def runTracker(self):
|
||||
foregroundPointsNum = 0
|
||||
|
||||
while True:
|
||||
frame = self.render.getNextFrame()
|
||||
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
||||
|
||||
if len(self.tracks) > 0:
|
||||
img0, img1 = self.prev_gray, frame_gray
|
||||
p0 = np.float32([tr[-1][0] for tr in self.tracks]).reshape(-1, 1, 2)
|
||||
p1, st, err = cv2.calcOpticalFlowPyrLK(img0, img1, p0, None, **lk_params)
|
||||
p0r, st, err = cv2.calcOpticalFlowPyrLK(img1, img0, p1, None, **lk_params)
|
||||
d = abs(p0-p0r).reshape(-1, 2).max(-1)
|
||||
good = d < 1
|
||||
new_tracks = []
|
||||
for tr, (x, y), good_flag in zip(self.tracks, p1.reshape(-1, 2), good):
|
||||
if not good_flag:
|
||||
continue
|
||||
tr.append([(x, y), self.frame_idx])
|
||||
if len(tr) > self.track_len:
|
||||
del tr[0]
|
||||
new_tracks.append(tr)
|
||||
self.tracks = new_tracks
|
||||
|
||||
if self.frame_idx % self.detect_interval == 0:
|
||||
goodTracksCount = 0
|
||||
for tr in self.tracks:
|
||||
oldRect = self.render.getRectInTime(self.render.timeStep * tr[0][1])
|
||||
newRect = self.render.getRectInTime(self.render.timeStep * tr[-1][1])
|
||||
if isPointInRect(tr[0][0], oldRect) and isPointInRect(tr[-1][0], newRect):
|
||||
goodTracksCount += 1
|
||||
|
||||
if self.frame_idx == self.detect_interval:
|
||||
foregroundPointsNum = goodTracksCount
|
||||
|
||||
fgIndex = float(foregroundPointsNum) / (foregroundPointsNum + 1)
|
||||
fgRate = float(goodTracksCount) / (len(self.tracks) + 1)
|
||||
|
||||
if self.frame_idx > 0:
|
||||
self.assertGreater(fgIndex, 0.9)
|
||||
self.assertGreater(fgRate, 0.2)
|
||||
|
||||
mask = np.zeros_like(frame_gray)
|
||||
mask[:] = 255
|
||||
for x, y in [np.int32(tr[-1][0]) for tr in self.tracks]:
|
||||
cv2.circle(mask, (x, y), 5, 0, -1)
|
||||
p = cv2.goodFeaturesToTrack(frame_gray, mask = mask, **feature_params)
|
||||
if p is not None:
|
||||
for x, y in np.float32(p).reshape(-1, 2):
|
||||
self.tracks.append([[(x, y), self.frame_idx]])
|
||||
|
||||
self.frame_idx += 1
|
||||
self.prev_gray = frame_gray
|
||||
|
||||
if self.frame_idx > 300:
|
||||
break
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
Morphology operations.
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class morphology_test(NewOpenCVTests):
|
||||
|
||||
def test_morphology(self):
|
||||
|
||||
fn = 'samples/gpu/rubberwhale1.png'
|
||||
img = self.get_sample(fn)
|
||||
|
||||
modes = ['erode/dilate', 'open/close', 'blackhat/tophat', 'gradient']
|
||||
str_modes = ['ellipse', 'rect', 'cross']
|
||||
|
||||
referenceHashes = { modes[0]: '071a526425b79e45b4d0d71ef51b0562', modes[1] : '071a526425b79e45b4d0d71ef51b0562',
|
||||
modes[2] : '427e89f581b7df1b60a831b1ed4c8618', modes[3] : '0dd8ad251088a63d0dd022bcdc57361c'}
|
||||
|
||||
def update(cur_mode):
|
||||
cur_str_mode = str_modes[0]
|
||||
sz = 10
|
||||
iters = 1
|
||||
opers = cur_mode.split('/')
|
||||
if len(opers) > 1:
|
||||
sz = sz - 10
|
||||
op = opers[sz > 0]
|
||||
sz = abs(sz)
|
||||
else:
|
||||
op = opers[0]
|
||||
sz = sz*2+1
|
||||
|
||||
str_name = 'MORPH_' + cur_str_mode.upper()
|
||||
oper_name = 'MORPH_' + op.upper()
|
||||
|
||||
st = cv2.getStructuringElement(getattr(cv2, str_name), (sz, sz))
|
||||
return cv2.morphologyEx(img, getattr(cv2, oper_name), st, iterations=iters)
|
||||
|
||||
for mode in modes:
|
||||
res = update(mode)
|
||||
self.assertEqual(self.hashimg(res), referenceHashes[mode])
|
||||
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
MSER detector test
|
||||
'''
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class mser_test(NewOpenCVTests):
|
||||
def test_mser(self):
|
||||
|
||||
img = self.get_sample('cv/mser/puzzle.png', 0)
|
||||
smallImg = [
|
||||
[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
|
||||
[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
|
||||
[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
|
||||
[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
|
||||
[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
|
||||
[255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255],
|
||||
[255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255],
|
||||
[255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255],
|
||||
[255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255],
|
||||
[255, 255, 255, 255, 255, 255, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 255, 255, 255, 255],
|
||||
[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
|
||||
[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
|
||||
[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
|
||||
[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
|
||||
]
|
||||
thresharr = [ 0, 70, 120, 180, 255 ]
|
||||
kDelta = 5
|
||||
np.random.seed(10)
|
||||
|
||||
for i in range(100):
|
||||
|
||||
use_big_image = int(np.random.rand(1,1)*7) != 0
|
||||
invert = int(np.random.rand(1,1)*2) != 0
|
||||
binarize = int(np.random.rand(1,1)*5) != 0 if use_big_image else False
|
||||
blur = True #int(np.random.rand(1,1)*2) != 0 #binarized images are processed incorrectly
|
||||
thresh = thresharr[int(np.random.rand(1,1)*5)]
|
||||
src0 = img if use_big_image else np.array(smallImg).astype('uint8')
|
||||
src = src0.copy()
|
||||
|
||||
kMinArea = 256 if use_big_image else 10
|
||||
kMaxArea = int(src.shape[0]*src.shape[1]/4)
|
||||
|
||||
mserExtractor = cv2.MSER(kDelta, kMinArea, kMaxArea)
|
||||
if invert:
|
||||
cv2.bitwise_not(src, src)
|
||||
if binarize:
|
||||
_, src = cv2.threshold(src, thresh, 255, cv2.THRESH_BINARY)
|
||||
if blur:
|
||||
src = cv2.GaussianBlur(src, (5, 5), 1.5, 1.5)
|
||||
minRegs = 7 if use_big_image else 2
|
||||
maxRegs = 1000 if use_big_image else 15
|
||||
if binarize and (thresh == 0 or thresh == 255):
|
||||
minRegs = maxRegs = 0
|
||||
msers = mserExtractor.detect(src)
|
||||
nmsers = len(msers)
|
||||
self.assertLessEqual(minRegs, nmsers)
|
||||
self.assertGreaterEqual(maxRegs, nmsers)
|
||||
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
example to detect upright people in images using HOG features
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
|
||||
def inside(r, q):
|
||||
rx, ry, rw, rh = r
|
||||
qx, qy, qw, qh = q
|
||||
return rx > qx and ry > qy and rx + rw < qx + qw and ry + rh < qy + qh
|
||||
|
||||
from tests_common import NewOpenCVTests, intersectionRate
|
||||
|
||||
class peopledetect_test(NewOpenCVTests):
|
||||
def test_peopledetect(self):
|
||||
|
||||
hog = cv2.HOGDescriptor()
|
||||
hog.setSVMDetector( cv2.HOGDescriptor_getDefaultPeopleDetector() )
|
||||
|
||||
dirPath = 'samples/gpu/'
|
||||
samples = ['basketball1.png', 'basketball2.png']
|
||||
|
||||
testPeople = [
|
||||
[[23, 76, 164, 477], [440, 22, 637, 478]],
|
||||
[[23, 76, 164, 477], [440, 22, 637, 478]]
|
||||
]
|
||||
|
||||
eps = 0.5
|
||||
|
||||
for sample in samples:
|
||||
|
||||
img = self.get_sample(dirPath + sample, 0)
|
||||
|
||||
found, w = hog.detectMultiScale(img, winStride=(8,8), padding=(32,32), scale=1.05)
|
||||
found_filtered = []
|
||||
for ri, r in enumerate(found):
|
||||
for qi, q in enumerate(found):
|
||||
if ri != qi and inside(r, q):
|
||||
break
|
||||
else:
|
||||
found_filtered.append(r)
|
||||
|
||||
matches = 0
|
||||
|
||||
for i in range(len(found_filtered)):
|
||||
for j in range(len(testPeople)):
|
||||
|
||||
found_rect = (found_filtered[i][0], found_filtered[i][1],
|
||||
found_filtered[i][0] + found_filtered[i][2],
|
||||
found_filtered[i][1] + found_filtered[i][3])
|
||||
|
||||
if intersectionRate(found_rect, testPeople[j][0]) > eps or intersectionRate(found_rect, testPeople[j][1]) > eps:
|
||||
matches += 1
|
||||
|
||||
self.assertGreater(matches, 0)
|
||||
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
Simple "Square Detector" program.
|
||||
|
||||
Loads several images sequentially and tries to find squares in each image.
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
import sys
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
if PY3:
|
||||
xrange = range
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
|
||||
def angle_cos(p0, p1, p2):
|
||||
d1, d2 = (p0-p1).astype('float'), (p2-p1).astype('float')
|
||||
return abs( np.dot(d1, d2) / np.sqrt( np.dot(d1, d1)*np.dot(d2, d2) ) )
|
||||
|
||||
def find_squares(img):
|
||||
img = cv2.GaussianBlur(img, (5, 5), 0)
|
||||
squares = []
|
||||
for gray in cv2.split(img):
|
||||
for thrs in xrange(0, 255, 26):
|
||||
if thrs == 0:
|
||||
bin = cv2.Canny(gray, 0, 50, apertureSize=5)
|
||||
bin = cv2.dilate(bin, None)
|
||||
else:
|
||||
retval, bin = cv2.threshold(gray, thrs, 255, cv2.THRESH_BINARY)
|
||||
contours, hierarchy = cv2.findContours(bin, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
|
||||
for cnt in contours:
|
||||
cnt_len = cv2.arcLength(cnt, True)
|
||||
cnt = cv2.approxPolyDP(cnt, 0.02*cnt_len, True)
|
||||
if len(cnt) == 4 and cv2.contourArea(cnt) > 1000 and cv2.isContourConvex(cnt):
|
||||
cnt = cnt.reshape(-1, 2)
|
||||
max_cos = np.max([angle_cos( cnt[i], cnt[(i+1) % 4], cnt[(i+2) % 4] ) for i in xrange(4)])
|
||||
if max_cos < 0.1 and filterSquares(squares, cnt):
|
||||
squares.append(cnt)
|
||||
|
||||
return squares
|
||||
|
||||
def intersectionRate(s1, s2):
|
||||
area, intersection = cv2.intersectConvexConvex(np.array(s1), np.array(s2))
|
||||
return 2 * area / (cv2.contourArea(np.array(s1)) + cv2.contourArea(np.array(s2)))
|
||||
|
||||
def filterSquares(squares, square):
|
||||
|
||||
for i in range(len(squares)):
|
||||
if intersectionRate(squares[i], square) > 0.95:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class squares_test(NewOpenCVTests):
|
||||
|
||||
def test_squares(self):
|
||||
|
||||
img = self.get_sample('samples/cpp/pic1.png')
|
||||
squares = find_squares(img)
|
||||
|
||||
testSquares = [
|
||||
[[43, 25],
|
||||
[43, 129],
|
||||
[232, 129],
|
||||
[232, 25]],
|
||||
|
||||
[[252, 87],
|
||||
[324, 40],
|
||||
[387, 137],
|
||||
[315, 184]],
|
||||
|
||||
[[154, 178],
|
||||
[196, 180],
|
||||
[198, 278],
|
||||
[154, 278]],
|
||||
|
||||
[[0, 0],
|
||||
[400, 0],
|
||||
[400, 300],
|
||||
[0, 300]]
|
||||
]
|
||||
|
||||
matches_counter = 0
|
||||
for i in range(len(squares)):
|
||||
for j in range(len(testSquares)):
|
||||
if intersectionRate(squares[i], testSquares[j]) > 0.9:
|
||||
matches_counter += 1
|
||||
|
||||
self.assertGreater(matches_counter / len(testSquares), 0.9)
|
||||
self.assertLess( (len(squares) - matches_counter) / len(squares), 0.2)
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
Texture flow direction estimation.
|
||||
|
||||
Sample shows how cv2.cornerEigenValsAndVecs function can be used
|
||||
to estimate image texture flow direction.
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
import sys
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
|
||||
class texture_flow_test(NewOpenCVTests):
|
||||
|
||||
def test_texture_flow(self):
|
||||
|
||||
img = self.get_sample('samples/cpp/pic6.png')
|
||||
|
||||
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||
h, w = img.shape[:2]
|
||||
|
||||
eigen = cv2.cornerEigenValsAndVecs(gray, 15, 3)
|
||||
eigen = eigen.reshape(h, w, 3, 2) # [[e1, e2], v1, v2]
|
||||
flow = eigen[:,:,2]
|
||||
|
||||
vis = img.copy()
|
||||
vis[:] = (192 + np.uint32(vis)) / 2
|
||||
d = 80
|
||||
points = np.dstack( np.mgrid[d/2:w:d, d/2:h:d] ).reshape(-1, 2)
|
||||
|
||||
textureVectors = []
|
||||
|
||||
for x, y in np.int32(points):
|
||||
textureVectors.append(np.int32(flow[y, x]*d))
|
||||
|
||||
eps = 0.05
|
||||
|
||||
testTextureVectors = [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0],
|
||||
[-38, 70], [-79, 3], [0, 0], [0, 0], [-39, 69], [-79, -1],
|
||||
[0, 0], [0, 0], [0, -79], [17, -78], [-48, -63], [65, -46],
|
||||
[-69, -39], [-48, -63]]
|
||||
|
||||
for i in range(len(testTextureVectors)):
|
||||
self.assertLessEqual(cv2.norm(textureVectors[i] - testTextureVectors[i], cv2.NORM_L2), eps)
|
||||
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
Watershed segmentation test
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class watershed_test(NewOpenCVTests):
|
||||
def test_watershed(self):
|
||||
|
||||
img = self.get_sample('cv/inpaint/orig.png')
|
||||
markers = self.get_sample('cv/watershed/wshed_exp.png', 0)
|
||||
refSegments = self.get_sample('cv/watershed/wshed_segments.png')
|
||||
|
||||
if img is None or markers is None:
|
||||
self.assertEqual(0, 1, 'Missing test data')
|
||||
|
||||
colors = np.int32( list(np.ndindex(3, 3, 3)) ) * 122
|
||||
cv2.watershed(img, np.int32(markers))
|
||||
segments = colors[np.maximum(markers, 0)]
|
||||
|
||||
if refSegments is None:
|
||||
refSegments = segments.copy()
|
||||
cv2.imwrite(self.extraTestDataPath + '/cv/watershed/wshed_segments.png', refSegments)
|
||||
|
||||
self.assertLess(cv2.norm(segments - refSegments, cv2.NORM_L1) / 255.0, 50)
|
||||
@@ -0,0 +1,185 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
import hashlib
|
||||
import os
|
||||
import numpy as np
|
||||
import cv2
|
||||
import cv2.cv as cv
|
||||
|
||||
# Python 3 moved urlopen to urllib.requests
|
||||
try:
|
||||
from urllib.request import urlopen
|
||||
except ImportError:
|
||||
from urllib import urlopen
|
||||
|
||||
class OpenCVTests(unittest.TestCase):
|
||||
|
||||
# path to local repository folder containing 'samples' folder
|
||||
repoPath = None
|
||||
# github repository url
|
||||
repoUrl = 'https://raw.github.com/Itseez/opencv/2.4'
|
||||
# path to local folder containing 'camera_calibration.tar.gz'
|
||||
dataPath = None
|
||||
# data url
|
||||
dataUrl = 'http://docs.opencv.org/data'
|
||||
|
||||
depths = [ cv.IPL_DEPTH_8U, cv.IPL_DEPTH_8S, cv.IPL_DEPTH_16U, cv.IPL_DEPTH_16S, cv.IPL_DEPTH_32S, cv.IPL_DEPTH_32F, cv.IPL_DEPTH_64F ]
|
||||
|
||||
mat_types = [
|
||||
cv.CV_8UC1,
|
||||
cv.CV_8UC2,
|
||||
cv.CV_8UC3,
|
||||
cv.CV_8UC4,
|
||||
cv.CV_8SC1,
|
||||
cv.CV_8SC2,
|
||||
cv.CV_8SC3,
|
||||
cv.CV_8SC4,
|
||||
cv.CV_16UC1,
|
||||
cv.CV_16UC2,
|
||||
cv.CV_16UC3,
|
||||
cv.CV_16UC4,
|
||||
cv.CV_16SC1,
|
||||
cv.CV_16SC2,
|
||||
cv.CV_16SC3,
|
||||
cv.CV_16SC4,
|
||||
cv.CV_32SC1,
|
||||
cv.CV_32SC2,
|
||||
cv.CV_32SC3,
|
||||
cv.CV_32SC4,
|
||||
cv.CV_32FC1,
|
||||
cv.CV_32FC2,
|
||||
cv.CV_32FC3,
|
||||
cv.CV_32FC4,
|
||||
cv.CV_64FC1,
|
||||
cv.CV_64FC2,
|
||||
cv.CV_64FC3,
|
||||
cv.CV_64FC4,
|
||||
]
|
||||
mat_types_single = [
|
||||
cv.CV_8UC1,
|
||||
cv.CV_8SC1,
|
||||
cv.CV_16UC1,
|
||||
cv.CV_16SC1,
|
||||
cv.CV_32SC1,
|
||||
cv.CV_32FC1,
|
||||
cv.CV_64FC1,
|
||||
]
|
||||
|
||||
def depthsize(self, d):
|
||||
return { cv.IPL_DEPTH_8U : 1,
|
||||
cv.IPL_DEPTH_8S : 1,
|
||||
cv.IPL_DEPTH_16U : 2,
|
||||
cv.IPL_DEPTH_16S : 2,
|
||||
cv.IPL_DEPTH_32S : 4,
|
||||
cv.IPL_DEPTH_32F : 4,
|
||||
cv.IPL_DEPTH_64F : 8 }[d]
|
||||
|
||||
def get_sample(self, filename, iscolor = cv.CV_LOAD_IMAGE_COLOR):
|
||||
if not filename in self.image_cache:
|
||||
filedata = None
|
||||
if OpenCVTests.repoPath is not None:
|
||||
candidate = OpenCVTests.repoPath + '/' + filename
|
||||
if os.path.isfile(candidate):
|
||||
with open(candidate, 'rb') as f:
|
||||
filedata = f.read()
|
||||
if filedata is None:
|
||||
filedata = urllib.urlopen(OpenCVTests.repoUrl + '/' + filename).read()
|
||||
imagefiledata = cv.CreateMatHeader(1, len(filedata), cv.CV_8UC1)
|
||||
cv.SetData(imagefiledata, filedata, len(filedata))
|
||||
self.image_cache[filename] = cv.DecodeImageM(imagefiledata, iscolor)
|
||||
return self.image_cache[filename]
|
||||
|
||||
def get_data(self, filename, urlbase):
|
||||
if (not os.path.isfile(filename)):
|
||||
if OpenCVTests.dataPath is not None:
|
||||
candidate = OpenCVTests.dataPath + '/' + filename
|
||||
if os.path.isfile(candidate):
|
||||
return candidate
|
||||
urllib.urlretrieve(urlbase + '/' + filename, filename)
|
||||
return filename
|
||||
|
||||
def setUp(self):
|
||||
self.image_cache = {}
|
||||
|
||||
def snap(self, img):
|
||||
self.snapL([img])
|
||||
|
||||
def snapL(self, L):
|
||||
for i,img in enumerate(L):
|
||||
cv.NamedWindow("snap-%d" % i, 1)
|
||||
cv.ShowImage("snap-%d" % i, img)
|
||||
cv.WaitKey()
|
||||
cv.DestroyAllWindows()
|
||||
|
||||
def hashimg(self, im):
|
||||
""" Compute a hash for an image, useful for image comparisons """
|
||||
return hashlib.md5(im.tostring()).digest()
|
||||
|
||||
|
||||
class NewOpenCVTests(unittest.TestCase):
|
||||
|
||||
# path to local repository folder containing 'samples' folder
|
||||
repoPath = None
|
||||
extraTestDataPath = None
|
||||
# github repository url
|
||||
repoUrl = 'https://raw.github.com/Itseez/opencv/master'
|
||||
|
||||
def get_sample(self, filename, iscolor = cv2.IMREAD_COLOR):
|
||||
if not filename in self.image_cache:
|
||||
filedata = None
|
||||
if NewOpenCVTests.repoPath is not None:
|
||||
candidate = NewOpenCVTests.repoPath + '/' + filename
|
||||
if os.path.isfile(candidate):
|
||||
with open(candidate, 'rb') as f:
|
||||
filedata = f.read()
|
||||
if NewOpenCVTests.extraTestDataPath is not None:
|
||||
candidate = NewOpenCVTests.extraTestDataPath + '/' + filename
|
||||
if os.path.isfile(candidate):
|
||||
with open(candidate, 'rb') as f:
|
||||
filedata = f.read()
|
||||
if filedata is None:
|
||||
return None#filedata = urlopen(NewOpenCVTests.repoUrl + '/' + filename).read()
|
||||
self.image_cache[filename] = cv2.imdecode(np.fromstring(filedata, dtype=np.uint8), iscolor)
|
||||
return self.image_cache[filename]
|
||||
|
||||
def setUp(self):
|
||||
cv2.setRNGSeed(10)
|
||||
self.image_cache = {}
|
||||
|
||||
def hashimg(self, im):
|
||||
""" Compute a hash for an image, useful for image comparisons """
|
||||
return hashlib.md5(im.tostring()).hexdigest()
|
||||
|
||||
if sys.version_info[:2] == (2, 6):
|
||||
def assertLess(self, a, b, msg=None):
|
||||
if not a < b:
|
||||
self.fail('%s not less than %s' % (repr(a), repr(b)))
|
||||
|
||||
def assertLessEqual(self, a, b, msg=None):
|
||||
if not a <= b:
|
||||
self.fail('%s not less than or equal to %s' % (repr(a), repr(b)))
|
||||
|
||||
def assertGreater(self, a, b, msg=None):
|
||||
if not a > b:
|
||||
self.fail('%s not greater than %s' % (repr(a), repr(b)))
|
||||
|
||||
def intersectionRate(s1, s2):
|
||||
|
||||
x1, y1, x2, y2 = s1
|
||||
s1 = np.array([[x1, y1], [x2,y1], [x2, y2], [x1, y2]])
|
||||
|
||||
x1, y1, x2, y2 = s2
|
||||
s2 = np.array([[x1, y1], [x2,y1], [x2, y2], [x1, y2]])
|
||||
|
||||
area, intersection = cv2.intersectConvexConvex(s1, s2)
|
||||
return 2 * area / (cv2.contourArea(s1) + cv2.contourArea(s2))
|
||||
|
||||
def isPointInRect(p, rect):
|
||||
if rect[0] <= p[0] and rect[1] <=p[1] and p[0] <= rect[2] and p[1] <= rect[3]:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
@@ -1,78 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import urllib
|
||||
import cv2.cv as cv
|
||||
import Image
|
||||
import unittest
|
||||
|
||||
class TestLoadImage(unittest.TestCase):
|
||||
def setUp(self):
|
||||
open("large.jpg", "w").write(urllib.urlopen("http://www.cs.ubc.ca/labs/lci/curious_george/img/ROS_bug_imgs/IMG_3560.jpg").read())
|
||||
|
||||
def test_load(self):
|
||||
pilim = Image.open("large.jpg")
|
||||
cvim = cv.LoadImage("large.jpg")
|
||||
self.assert_(len(pilim.tostring()) == len(cvim.tostring()))
|
||||
|
||||
class Creating(unittest.TestCase):
|
||||
size=(640, 480)
|
||||
repeat=100
|
||||
def test_0_Create(self):
|
||||
image = cv.CreateImage(self.size, cv.IPL_DEPTH_8U, 1)
|
||||
cnt=cv.CountNonZero(image)
|
||||
self.assertEqual(cnt, 0, msg="Created image is not black. CountNonZero=%i" % cnt)
|
||||
|
||||
def test_2_CreateRepeat(self):
|
||||
cnt=0
|
||||
for i in range(self.repeat):
|
||||
image = cv.CreateImage(self.size, cv.IPL_DEPTH_8U, 1)
|
||||
cnt+=cv.CountNonZero(image)
|
||||
self.assertEqual(cnt, 0, msg="Created images are not black. Mean CountNonZero=%.3f" % (1.*cnt/self.repeat))
|
||||
|
||||
def test_2a_MemCreated(self):
|
||||
cnt=0
|
||||
v=[]
|
||||
for i in range(self.repeat):
|
||||
image = cv.CreateImage(self.size, cv.IPL_DEPTH_8U, 1)
|
||||
cv.FillPoly(image, [[(0, 0), (0, 100), (100, 0)]], 0)
|
||||
cnt+=cv.CountNonZero(image)
|
||||
v.append(image)
|
||||
self.assertEqual(cnt, 0, msg="Memorized images are not black. Mean CountNonZero=%.3f" % (1.*cnt/self.repeat))
|
||||
|
||||
def test_3_tostirng(self):
|
||||
image = cv.CreateImage(self.size, cv.IPL_DEPTH_8U, 1)
|
||||
image.tostring()
|
||||
cnt=cv.CountNonZero(image)
|
||||
self.assertEqual(cnt, 0, msg="After tostring(): CountNonZero=%i" % cnt)
|
||||
|
||||
def test_40_tostringRepeat(self):
|
||||
cnt=0
|
||||
image = cv.CreateImage(self.size, cv.IPL_DEPTH_8U, 1)
|
||||
cv.Set(image, cv.Scalar(0,0,0,0))
|
||||
for i in range(self.repeat*100):
|
||||
image.tostring()
|
||||
cnt=cv.CountNonZero(image)
|
||||
self.assertEqual(cnt, 0, msg="Repeating tostring(): Mean CountNonZero=%.3f" % (1.*cnt/self.repeat))
|
||||
|
||||
def test_41_CreateToStringRepeat(self):
|
||||
cnt=0
|
||||
for i in range(self.repeat*100):
|
||||
image = cv.CreateImage(self.size, cv.IPL_DEPTH_8U, 1)
|
||||
cv.Set(image, cv.Scalar(0,0,0,0))
|
||||
image.tostring()
|
||||
cnt+=cv.CountNonZero(image)
|
||||
self.assertEqual(cnt, 0, msg="Repeating create and tostring(): Mean CountNonZero=%.3f" % (1.*cnt/self.repeat))
|
||||
|
||||
def test_4a_MemCreatedToString(self):
|
||||
cnt=0
|
||||
v=[]
|
||||
for i in range(self.repeat):
|
||||
image = cv.CreateImage(self.size, cv.IPL_DEPTH_8U, 1)
|
||||
cv.Set(image, cv.Scalar(0,0,0,0))
|
||||
image.tostring()
|
||||
cnt+=cv.CountNonZero(image)
|
||||
v.append(image)
|
||||
self.assertEqual(cnt, 0, msg="Repeating and memorizing after tostring(): Mean CountNonZero=%.3f" % (1.*cnt/self.repeat))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
from numpy import pi, sin, cos
|
||||
|
||||
import cv2
|
||||
|
||||
defaultSize = 512
|
||||
|
||||
class TestSceneRender():
|
||||
|
||||
def __init__(self, bgImg = None, fgImg = None, deformation = False, noise = 0.0, speed = 0.25, **params):
|
||||
self.time = 0.0
|
||||
self.timeStep = 1.0 / 30.0
|
||||
self.foreground = fgImg
|
||||
self.deformation = deformation
|
||||
self.noise = noise
|
||||
self.speed = speed
|
||||
|
||||
if bgImg is not None:
|
||||
self.sceneBg = bgImg.copy()
|
||||
else:
|
||||
self.sceneBg = np.zeros(defaultSize, defaultSize, np.uint8)
|
||||
|
||||
self.w = self.sceneBg.shape[0]
|
||||
self.h = self.sceneBg.shape[1]
|
||||
|
||||
if fgImg is not None:
|
||||
self.foreground = fgImg.copy()
|
||||
self.center = self.currentCenter = (int(self.w/2 - fgImg.shape[0]/2), int(self.h/2 - fgImg.shape[1]/2))
|
||||
|
||||
self.xAmpl = self.sceneBg.shape[0] - (self.center[0] + fgImg.shape[0])
|
||||
self.yAmpl = self.sceneBg.shape[1] - (self.center[1] + fgImg.shape[1])
|
||||
|
||||
self.initialRect = np.array([ (self.h/2, self.w/2), (self.h/2, self.w/2 + self.w/10),
|
||||
(self.h/2 + self.h/10, self.w/2 + self.w/10), (self.h/2 + self.h/10, self.w/2)]).astype(int)
|
||||
self.currentRect = self.initialRect
|
||||
np.random.seed(10)
|
||||
|
||||
def getXOffset(self, time):
|
||||
return int(self.xAmpl*cos(time*self.speed))
|
||||
|
||||
|
||||
def getYOffset(self, time):
|
||||
return int(self.yAmpl*sin(time*self.speed))
|
||||
|
||||
def setInitialRect(self, rect):
|
||||
self.initialRect = rect
|
||||
|
||||
def getRectInTime(self, time):
|
||||
|
||||
if self.foreground is not None:
|
||||
tmp = np.array(self.center) + np.array((self.getXOffset(time), self.getYOffset(time)))
|
||||
x0, y0 = tmp
|
||||
x1, y1 = tmp + self.foreground.shape[0:2]
|
||||
return np.array([y0, x0, y1, x1])
|
||||
else:
|
||||
x0, y0 = self.initialRect[0] + np.array((self.getXOffset(time), self.getYOffset(time)))
|
||||
x1, y1 = self.initialRect[2] + np.array((self.getXOffset(time), self.getYOffset(time)))
|
||||
return np.array([y0, x0, y1, x1])
|
||||
|
||||
def getCurrentRect(self):
|
||||
|
||||
if self.foreground is not None:
|
||||
|
||||
x0 = self.currentCenter[0]
|
||||
y0 = self.currentCenter[1]
|
||||
x1 = self.currentCenter[0] + self.foreground.shape[0]
|
||||
y1 = self.currentCenter[1] + self.foreground.shape[1]
|
||||
return np.array([y0, x0, y1, x1])
|
||||
else:
|
||||
x0, y0 = self.currentRect[0]
|
||||
x1, y1 = self.currentRect[2]
|
||||
return np.array([x0, y0, x1, y1])
|
||||
|
||||
def getNextFrame(self):
|
||||
img = self.sceneBg.copy()
|
||||
|
||||
if self.foreground is not None:
|
||||
self.currentCenter = (self.center[0] + self.getXOffset(self.time), self.center[1] + self.getYOffset(self.time))
|
||||
img[self.currentCenter[0]:self.currentCenter[0]+self.foreground.shape[0],
|
||||
self.currentCenter[1]:self.currentCenter[1]+self.foreground.shape[1]] = self.foreground
|
||||
else:
|
||||
self.currentRect = self.initialRect + np.int( 30*cos(self.time) + 50*sin(self.time/3))
|
||||
if self.deformation:
|
||||
self.currentRect[1:3] += int(self.h/20*cos(self.time))
|
||||
cv2.fillConvexPoly(img, self.currentRect, (0, 0, 255))
|
||||
|
||||
self.time += self.timeStep
|
||||
|
||||
if self.noise:
|
||||
noise = np.zeros(self.sceneBg.shape, np.int8)
|
||||
cv2.randn(noise, np.zeros(3), np.ones(3)*255*self.noise)
|
||||
img = cv2.add(img, noise, dtype=cv2.CV_8UC3)
|
||||
return img
|
||||
|
||||
def resetTime(self):
|
||||
self.time = 0.0
|
||||
@@ -31,7 +31,7 @@ if __name__ == "__main__":
|
||||
parser.add_argument("--list", action="store_true", default=False, help="List available tests (executables)")
|
||||
parser.add_argument("--list_short", action="store_true", default=False, help="List available tests (aliases)")
|
||||
parser.add_argument("--list_short_main", action="store_true", default=False, help="List available tests (main repository, aliases)")
|
||||
parser.add_argument("--configuration", metavar="CFG", default="", help="Visual Studio: force Debug or Release configuration")
|
||||
parser.add_argument("--configuration", metavar="CFG", default=None, help="Force Debug or Release configuration (for Visual Studio and Java tests build)")
|
||||
parser.add_argument("-n", "--dry_run", action="store_true", help="Do not run the tests")
|
||||
parser.add_argument("-v", "--verbose", action="store_true", default=False, help="Print more debug information")
|
||||
|
||||
@@ -95,12 +95,12 @@ if __name__ == "__main__":
|
||||
try:
|
||||
if not os.path.isdir(path):
|
||||
raise Err("Not a directory (should contain CMakeCache.txt ot test executables)")
|
||||
cache = CMakeCache()
|
||||
cache = CMakeCache(args.configuration)
|
||||
fname = os.path.join(path, "CMakeCache.txt")
|
||||
|
||||
if os.path.isfile(fname):
|
||||
log.debug("Reading cmake cache file: %s", fname)
|
||||
cache.read(path, fname, args.configuration)
|
||||
cache.read(path, fname)
|
||||
else:
|
||||
log.debug("Assuming folder contains tests: %s", path)
|
||||
cache.setDummy(path)
|
||||
|
||||
@@ -48,22 +48,27 @@ class TestSuite(object):
|
||||
return sorted(self.getAliases(fname), key = len)[0]
|
||||
|
||||
def getAliases(self, fname):
|
||||
def getCuts(fname, prefix):
|
||||
# filename w/o extension (opencv_test_core)
|
||||
noext = re.sub(r"\.(exe|apk)$", '', fname)
|
||||
# filename w/o prefix (core.exe)
|
||||
nopref = fname
|
||||
if fname.startswith(prefix):
|
||||
nopref = fname[len(prefix):]
|
||||
# filename w/o prefix and extension (core)
|
||||
noprefext = noext
|
||||
if noext.startswith(prefix):
|
||||
noprefext = noext[len(prefix):]
|
||||
return noext, nopref, noprefext
|
||||
# input is full path ('/home/.../bin/opencv_test_core') or 'java'
|
||||
res = [fname]
|
||||
fname = os.path.basename(fname)
|
||||
res.append(fname) # filename (opencv_test_core.exe)
|
||||
noext = re.sub(r"\.(exe|apk)$", '', fname)
|
||||
res.append(noext) # filename w/o extension (opencv_test_core)
|
||||
nopref = None
|
||||
if fname.startswith(self.nameprefix):
|
||||
nopref = fname[len(self.nameprefix):]
|
||||
res.append(nopref) # filename w/o prefix (core)
|
||||
if noext.startswith(self.nameprefix):
|
||||
res.append(noext[len(self.nameprefix):])
|
||||
if self.options.configuration == "Debug":
|
||||
res.append(re.sub(r"d$", '', noext)) # MSVC debug config, remove 'd' suffix
|
||||
if nopref:
|
||||
res.append(re.sub(r"d$", '', nopref)) # MSVC debug config, remove 'd' suffix
|
||||
for s in getCuts(fname, self.nameprefix):
|
||||
res.append(s)
|
||||
if self.cache.build_type == "Debug" and "Visual Studio" in self.cache.cmake_generator:
|
||||
res.append(re.sub(r"d$", '', s)) # MSVC debug config, remove 'd' suffix
|
||||
log.debug("Aliases: %s", set(res))
|
||||
return set(res)
|
||||
|
||||
def getTest(self, name):
|
||||
@@ -101,10 +106,7 @@ class TestSuite(object):
|
||||
args = args[:]
|
||||
exe = os.path.abspath(path)
|
||||
if path == "java":
|
||||
cfg = self.cache.build_type
|
||||
if self.options.configuration:
|
||||
cfg = self.options.configuration
|
||||
cmd = [self.cache.ant_executable, "-Dopencv.build.type=%s" % cfg, "buildAndTest"]
|
||||
cmd = [self.cache.ant_executable, "-Dopencv.build.type=%s" % self.cache.build_type, "buildAndTest"]
|
||||
ret = execute(cmd, cwd = self.cache.java_test_binary_dir + "/.build")
|
||||
return None, ret
|
||||
else:
|
||||
|
||||
@@ -152,7 +152,7 @@ parse_patterns = (
|
||||
{'name': "opencv_home", 'default': None, 'pattern': re.compile(r"^OpenCV_SOURCE_DIR:STATIC=(.+)$")},
|
||||
{'name': "opencv_build", 'default': None, 'pattern': re.compile(r"^OpenCV_BINARY_DIR:STATIC=(.+)$")},
|
||||
{'name': "tests_dir", 'default': None, 'pattern': re.compile(r"^EXECUTABLE_OUTPUT_PATH:PATH=(.+)$")},
|
||||
{'name': "build_type", 'default': "Release", 'pattern': re.compile(r"^CMAKE_BUILD_TYPE:STRING=(.*)$")},
|
||||
{'name': "build_type", 'default': "Release", 'pattern': re.compile(r"^CMAKE_BUILD_TYPE:\w+=(.*)$")},
|
||||
{'name': "git_executable", 'default': None, 'pattern': re.compile(r"^GIT_EXECUTABLE:FILEPATH=(.*)$")},
|
||||
{'name': "cxx_flags", 'default': "", 'pattern': re.compile(r"^CMAKE_CXX_FLAGS:STRING=(.*)$")},
|
||||
{'name': "cxx_flags_debug", 'default': "", 'pattern': re.compile(r"^CMAKE_CXX_FLAGS_DEBUG:STRING=(.*)$")},
|
||||
@@ -174,17 +174,19 @@ parse_patterns = (
|
||||
)
|
||||
|
||||
class CMakeCache:
|
||||
def __init__(self):
|
||||
def __init__(self, cfg = None):
|
||||
self.setDefaultAttrs()
|
||||
self.cmake_home_vcver = None
|
||||
self.opencv_home_vcver = None
|
||||
self.featuresSIMD = None
|
||||
self.main_modules = []
|
||||
if cfg:
|
||||
self.build_type = cfg
|
||||
|
||||
def setDummy(self, path):
|
||||
self.tests_dir = os.path.normpath(path)
|
||||
|
||||
def read(self, path, fname, cfg):
|
||||
def read(self, path, fname):
|
||||
rx = re.compile(r'^opencv_(\w+)_SOURCE_DIR:STATIC=(.*)$')
|
||||
module_paths = {} # name -> path
|
||||
with open(fname, "rt") as cachefile:
|
||||
@@ -213,10 +215,7 @@ class CMakeCache:
|
||||
|
||||
# fix VS test binary path (add Debug or Release)
|
||||
if "Visual Studio" in self.cmake_generator:
|
||||
if cfg:
|
||||
self.tests_dir = os.path.join(self.tests_dir, self.options.configuration)
|
||||
else:
|
||||
self.tests_dir = os.path.join(self.tests_dir, self.build_type)
|
||||
self.tests_dir = os.path.join(self.tests_dir, self.build_type)
|
||||
|
||||
self.cmake_home_vcver = readGitVersion(self.git_executable, self.cmake_home)
|
||||
if self.opencv_home == self.cmake_home:
|
||||
|
||||
@@ -34,7 +34,6 @@ add_library(opencv_info SHARED info.c)
|
||||
set_target_properties(${the_module} PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}
|
||||
RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}
|
||||
INSTALL_NAME_DIR lib
|
||||
)
|
||||
|
||||
get_filename_component(lib_name "libopencv_info.so" NAME)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 929 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
Reference in New Issue
Block a user