Commit 898fbd77 authored by mshabunin's avatar mshabunin

Merge master

parents 337487d4 1df640a6
...@@ -226,6 +226,15 @@ CV_EXPORTS_W void estimatePoseSingleMarkers(InputArrayOfArrays corners, float ma ...@@ -226,6 +226,15 @@ CV_EXPORTS_W void estimatePoseSingleMarkers(InputArrayOfArrays corners, float ma
class CV_EXPORTS_W Board { class CV_EXPORTS_W Board {
public: public:
/**
* @brief Provide way to create Board by passing nessesary data. Specially needed in Python.
*
* @param objPoints array of object points of all the marker corners in the board
* @param dictionary the dictionary of markers employed for this board
* @param ids vector of the identifiers of the markers in the board
*
*/
CV_WRAP static Ptr<Board> create(InputArrayOfArrays objPoints, Ptr<Dictionary> &dictionary, InputArray ids);
// array of object points of all the marker corners in the board // array of object points of all the marker corners in the board
// each marker include its 4 corners, i.e. for M markers, the size is Mx4 // each marker include its 4 corners, i.e. for M markers, the size is Mx4
CV_PROP std::vector< std::vector< Point3f > > objPoints; CV_PROP std::vector< std::vector< Point3f > > objPoints;
...@@ -322,8 +331,9 @@ class CV_EXPORTS_W GridBoard : public Board { ...@@ -322,8 +331,9 @@ class CV_EXPORTS_W GridBoard : public Board {
* @param distCoeffs vector of distortion coefficients * @param distCoeffs vector of distortion coefficients
* \f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6],[s_1, s_2, s_3, s_4]])\f$ of 4, 5, 8 or 12 elements * \f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6],[s_1, s_2, s_3, s_4]])\f$ of 4, 5, 8 or 12 elements
* @param rvec Output vector (e.g. cv::Mat) corresponding to the rotation vector of the board * @param rvec Output vector (e.g. cv::Mat) corresponding to the rotation vector of the board
* (@sa Rodrigues). * (@sa Rodrigues). Used as initial guess if not empty.
* @param tvec Output vector (e.g. cv::Mat) corresponding to the translation vector of the board. * @param tvec Output vector (e.g. cv::Mat) corresponding to the translation vector of the board.
* Used as initial guess if not empty.
* *
* This function receives the detected markers and returns the pose of a marker board composed * This function receives the detected markers and returns the pose of a marker board composed
* by those markers. * by those markers.
...@@ -474,7 +484,7 @@ void _drawPlanarBoardImpl(Board *board, Size outSize, OutputArray img, ...@@ -474,7 +484,7 @@ void _drawPlanarBoardImpl(Board *board, Size outSize, OutputArray img,
* @brief Calibrate a camera using aruco markers * @brief Calibrate a camera using aruco markers
* *
* @param corners vector of detected marker corners in all frames. * @param corners vector of detected marker corners in all frames.
* The corners should have the same format returned by detectMarkers (@sa detectMarkers). * The corners should have the same format returned by detectMarkers (see #detectMarkers).
* @param ids list of identifiers for each marker in corners * @param ids list of identifiers for each marker in corners
* @param counter number of markers in each frame so that corners and ids can be split * @param counter number of markers in each frame so that corners and ids can be split
* @param board Marker Board layout * @param board Marker Board layout
...@@ -491,20 +501,38 @@ void _drawPlanarBoardImpl(Board *board, Size outSize, OutputArray img, ...@@ -491,20 +501,38 @@ void _drawPlanarBoardImpl(Board *board, Size outSize, OutputArray img,
* from the model coordinate space (in which object points are specified) to the world coordinate * from the model coordinate space (in which object points are specified) to the world coordinate
* space, that is, a real position of the board pattern in the k-th pattern view (k=0.. *M* -1). * space, that is, a real position of the board pattern in the k-th pattern view (k=0.. *M* -1).
* @param tvecs Output vector of translation vectors estimated for each pattern view. * @param tvecs Output vector of translation vectors estimated for each pattern view.
* @param flags flags Different flags for the calibration process (@sa calibrateCamera) * @param stdDeviationsIntrinsics Output vector of standard deviations estimated for intrinsic parameters.
* Order of deviations values:
* \f$(f_x, f_y, c_x, c_y, k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6 , s_1, s_2, s_3,
* s_4, \tau_x, \tau_y)\f$ If one of parameters is not estimated, it's deviation is equals to zero.
* @param stdDeviationsExtrinsics Output vector of standard deviations estimated for extrinsic parameters.
* Order of deviations values: \f$(R_1, T_1, \dotsc , R_M, T_M)\f$ where M is number of pattern views,
* \f$R_i, T_i\f$ are concatenated 1x3 vectors.
* @param perViewErrors Output vector of average re-projection errors estimated for each pattern view.
* @param flags flags Different flags for the calibration process (see #calibrateCamera for details).
* @param criteria Termination criteria for the iterative optimization algorithm. * @param criteria Termination criteria for the iterative optimization algorithm.
* *
* This function calibrates a camera using an Aruco Board. The function receives a list of * This function calibrates a camera using an Aruco Board. The function receives a list of
* detected markers from several views of the Board. The process is similar to the chessboard * detected markers from several views of the Board. The process is similar to the chessboard
* calibration in calibrateCamera(). The function returns the final re-projection error. * calibration in calibrateCamera(). The function returns the final re-projection error.
*/ */
CV_EXPORTS_W double calibrateCameraAruco( CV_EXPORTS_AS(calibrateCameraArucoExtended) double calibrateCameraAruco(
InputArrayOfArrays corners, InputArray ids, InputArray counter, const Ptr<Board> &board, InputArrayOfArrays corners, InputArray ids, InputArray counter, Ptr<Board> &board,
Size imageSize, InputOutputArray cameraMatrix, InputOutputArray distCoeffs, Size imageSize, InputOutputArray cameraMatrix, InputOutputArray distCoeffs,
OutputArrayOfArrays rvecs = noArray(), OutputArrayOfArrays tvecs = noArray(), int flags = 0, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs,
OutputArray stdDeviationsIntrinsics = noArray(), OutputArray stdDeviationsExtrinsics = noArray(),
OutputArray perViewErrors = noArray(), int flags = 0,
TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)); TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON));
/** @brief It's the same function as #calibrateCameraAruco but without calibration error estimation.
*/
CV_EXPORTS_W double calibrateCameraAruco(
InputArrayOfArrays corners, InputArray ids, InputArray counter, const Ptr<Board> &board,
Size imageSize, InputOutputArray cameraMatrix, InputOutputArray distCoeffs,
OutputArrayOfArrays rvecs = noArray(), OutputArrayOfArrays tvecs = noArray(), int flags = 0,
TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON));
//! @} //! @}
} }
......
...@@ -223,19 +223,36 @@ CV_EXPORTS_W void drawDetectedCornersCharuco(InputOutputArray image, InputArray ...@@ -223,19 +223,36 @@ CV_EXPORTS_W void drawDetectedCornersCharuco(InputOutputArray image, InputArray
* from the model coordinate space (in which object points are specified) to the world coordinate * from the model coordinate space (in which object points are specified) to the world coordinate
* space, that is, a real position of the board pattern in the k-th pattern view (k=0.. *M* -1). * space, that is, a real position of the board pattern in the k-th pattern view (k=0.. *M* -1).
* @param tvecs Output vector of translation vectors estimated for each pattern view. * @param tvecs Output vector of translation vectors estimated for each pattern view.
* @param flags flags Different flags for the calibration process (@sa calibrateCamera) * @param stdDeviationsIntrinsics Output vector of standard deviations estimated for intrinsic parameters.
* Order of deviations values:
* \f$(f_x, f_y, c_x, c_y, k_1, k_2, p_1, p_2, k_3, k_4, k_5, k_6 , s_1, s_2, s_3,
* s_4, \tau_x, \tau_y)\f$ If one of parameters is not estimated, it's deviation is equals to zero.
* @param stdDeviationsExtrinsics Output vector of standard deviations estimated for extrinsic parameters.
* Order of deviations values: \f$(R_1, T_1, \dotsc , R_M, T_M)\f$ where M is number of pattern views,
* \f$R_i, T_i\f$ are concatenated 1x3 vectors.
* @param perViewErrors Output vector of average re-projection errors estimated for each pattern view.
* @param flags flags Different flags for the calibration process (see #calibrateCamera for details).
* @param criteria Termination criteria for the iterative optimization algorithm. * @param criteria Termination criteria for the iterative optimization algorithm.
* *
* This function calibrates a camera using a set of corners of a Charuco Board. The function * This function calibrates a camera using a set of corners of a Charuco Board. The function
* receives a list of detected corners and its identifiers from several views of the Board. * receives a list of detected corners and its identifiers from several views of the Board.
* The function returns the final re-projection error. * The function returns the final re-projection error.
*/ */
CV_EXPORTS_W double calibrateCameraCharuco( CV_EXPORTS_AS(calibrateCameraCharucoExtended) double calibrateCameraCharuco(
InputArrayOfArrays charucoCorners, InputArrayOfArrays charucoIds, const Ptr<CharucoBoard> &board, InputArrayOfArrays charucoCorners, InputArrayOfArrays charucoIds, Ptr<CharucoBoard> &board,
Size imageSize, InputOutputArray cameraMatrix, InputOutputArray distCoeffs, Size imageSize, InputOutputArray cameraMatrix, InputOutputArray distCoeffs,
OutputArrayOfArrays rvecs = noArray(), OutputArrayOfArrays tvecs = noArray(), int flags = 0, OutputArrayOfArrays rvecs = noArray(), OutputArrayOfArrays tvecs = noArray(),
OutputArray stdDeviationsIntrinsics = noArray(), OutputArray stdDeviationsExtrinsics = noArray(),
OutputArray perViewErrors = noArray(), int flags = 0,
TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)); TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON));
/** @brief It's the same function as #calibrateCameraCharuco but without calibration error estimation.
*/
CV_EXPORTS_W double calibrateCameraCharuco(
InputArrayOfArrays charucoCorners, InputArrayOfArrays charucoIds, const Ptr<CharucoBoard> &board,
Size imageSize, InputOutputArray cameraMatrix, InputOutputArray distCoeffs,
OutputArrayOfArrays rvecs = noArray(), OutputArrayOfArrays tvecs = noArray(), int flags = 0,
TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON));
......
...@@ -158,7 +158,7 @@ int main(int argc, char *argv[]) { ...@@ -158,7 +158,7 @@ int main(int argc, char *argv[]) {
} }
int markersX = parser.get<int>("w"); int markersX = parser.get<int>("w");
int markersY = parser.get<int>("w"); int markersY = parser.get<int>("h");
float markerLength = parser.get<float>("l"); float markerLength = parser.get<float>("l");
float markerSeparation = parser.get<float>("s"); float markerSeparation = parser.get<float>("s");
int dictionaryId = parser.get<int>("d"); int dictionaryId = parser.get<int>("d");
......
This diff is collapsed.
This diff is collapsed.
...@@ -338,3 +338,72 @@ TEST(CV_ArucoRefine, accuracy) { ...@@ -338,3 +338,72 @@ TEST(CV_ArucoRefine, accuracy) {
CV_ArucoRefine test; CV_ArucoRefine test;
test.safe_run(); test.safe_run();
} }
TEST(CV_ArucoBoardPose, CheckNegativeZ)
{
double matrixData[9] = { -3.9062571886921410e+02, 0., 4.2350000000000000e+02,
0., 3.9062571886921410e+02, 2.3950000000000000e+02,
0., 0., 1 };
cv::Mat cameraMatrix = cv::Mat(3, 3, CV_64F, matrixData);
cv::Ptr<cv::aruco::Board> boardPtr(new cv::aruco::Board);
cv::aruco::Board& board = *boardPtr;
board.ids.push_back(0);
board.ids.push_back(1);
vector<cv::Point3f> pts3d;
pts3d.push_back(cv::Point3f(0.326198f, -0.030621f, 0.303620f));
pts3d.push_back(cv::Point3f(0.325340f, -0.100594f, 0.301862f));
pts3d.push_back(cv::Point3f(0.255859f, -0.099530f, 0.293416f));
pts3d.push_back(cv::Point3f(0.256717f, -0.029557f, 0.295174f));
board.objPoints.push_back(pts3d);
pts3d.clear();
pts3d.push_back(cv::Point3f(-0.033144f, -0.034819f, 0.245216f));
pts3d.push_back(cv::Point3f(-0.035507f, -0.104705f, 0.241987f));
pts3d.push_back(cv::Point3f(-0.105289f, -0.102120f, 0.237120f));
pts3d.push_back(cv::Point3f(-0.102926f, -0.032235f, 0.240349f));
board.objPoints.push_back(pts3d);
vector<vector<Point2f> > corners;
vector<Point2f> pts2d;
pts2d.push_back(cv::Point2f(37.7f, 203.3f));
pts2d.push_back(cv::Point2f(38.5f, 120.5f));
pts2d.push_back(cv::Point2f(105.5f, 115.8f));
pts2d.push_back(cv::Point2f(104.2f, 202.7f));
corners.push_back(pts2d);
pts2d.clear();
pts2d.push_back(cv::Point2f(476.0f, 184.2f));
pts2d.push_back(cv::Point2f(479.6f, 73.8f));
pts2d.push_back(cv::Point2f(590.9f, 77.0f));
pts2d.push_back(cv::Point2f(587.5f, 188.1f));
corners.push_back(pts2d);
Vec3d rvec, tvec;
int nUsed = cv::aruco::estimatePoseBoard(corners, board.ids, boardPtr, cameraMatrix, Mat(), rvec, tvec);
ASSERT_EQ(nUsed, 2);
cv::Matx33d rotm; cv::Point3d out;
cv::Rodrigues(rvec, rotm);
out = cv::Point3d(tvec) + rotm*Point3d(board.objPoints[0][0]);
ASSERT_GT(out.z, 0);
corners.clear(); pts2d.clear();
pts2d.push_back(cv::Point2f(38.4f, 204.5f));
pts2d.push_back(cv::Point2f(40.0f, 124.7f));
pts2d.push_back(cv::Point2f(102.0f, 119.1f));
pts2d.push_back(cv::Point2f(99.9f, 203.6f));
corners.push_back(pts2d);
pts2d.clear();
pts2d.push_back(cv::Point2f(476.0f, 184.3f));
pts2d.push_back(cv::Point2f(479.2f, 75.1f));
pts2d.push_back(cv::Point2f(588.7f, 79.2f));
pts2d.push_back(cv::Point2f(586.3f, 188.5f));
corners.push_back(pts2d);
nUsed = cv::aruco::estimatePoseBoard(corners, board.ids, boardPtr, cameraMatrix, Mat(), rvec, tvec);
ASSERT_EQ(nUsed, 2);
cv::Rodrigues(rvec, rotm);
out = cv::Point3d(tvec) + rotm*Point3d(board.objPoints[0][0]);
ASSERT_GT(out.z, 0);
}
...@@ -74,7 +74,7 @@ The parameters of estimatePoseBoard are: ...@@ -74,7 +74,7 @@ The parameters of estimatePoseBoard are:
- ```markerCorners``` and ```markerIds```: structures of detected markers from ```detectMarkers()``` function. - ```markerCorners``` and ```markerIds```: structures of detected markers from ```detectMarkers()``` function.
- ```board```: the ```Board``` object that defines the board layout and its ids - ```board```: the ```Board``` object that defines the board layout and its ids
- ```cameraMatrix``` and ```distCoeffs```: camera calibration parameters necessary for pose estimation. - ```cameraMatrix``` and ```distCoeffs```: camera calibration parameters necessary for pose estimation.
- ```rvec``` and ```tvec```: estimated pose of the Board. - ```rvec``` and ```tvec```: estimated pose of the Board. If not empty then treated as initial guess.
- The function returns the total number of markers employed for estimating the board pose. Note that not all the - The function returns the total number of markers employed for estimating the board pose. Note that not all the
markers provided in ```markerCorners``` and ```markerIds``` should be used, since only the markers whose ids are markers provided in ```markerCorners``` and ```markerIds``` should be used, since only the markers whose ids are
listed in the ```Board::ids``` structure are considered. listed in the ```Board::ids``` structure are considered.
......
...@@ -64,8 +64,8 @@ template <int depth, int channels> ...@@ -64,8 +64,8 @@ template <int depth, int channels>
std::string printPixel(const cv::Mat &mat, int spalte, int zeile) std::string printPixel(const cv::Mat &mat, int spalte, int zeile)
{ {
std::stringstream ss{}; std::stringstream ss{};
auto p = mat.at<cv::Vec<cvv::qtutil::DepthType<depth>, channels>>( typedef cv::Vec<cvv::qtutil::DepthType<depth>, channels> VecType;
zeile, spalte); const VecType &p = mat.at<VecType>(zeile, spalte);
putInStream<depth>(ss, p[0]); putInStream<depth>(ss, p[0]);
for (int c = 1; c < mat.channels(); c++) for (int c = 1; c < mat.channels(); c++)
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
TEST(LocationTest, FileLineFunction) TEST(LocationTest, FileLineFunction)
{ {
auto locationMacroResult = CVVISUAL_LOCATION; auto locationMacroResult = CVVISUAL_LOCATION;
auto line = __LINE__ - 1; size_t line = __LINE__ - 1;
auto file = __FILE__; auto file = __FILE__;
auto fun = CVVISUAL_FUNCTION_NAME_MACRO; auto fun = CVVISUAL_FUNCTION_NAME_MACRO;
EXPECT_EQ(locationMacroResult.isKnown, true); EXPECT_EQ(locationMacroResult.isKnown, true);
......
#include "test_precomp.hpp" #include "test_precomp.hpp"
CV_TEST_MAIN(".") CV_TEST_MAIN(".", /*Empty VA_ARGS for C++11*/)
...@@ -223,8 +223,7 @@ struct PointerStringPairHash { ...@@ -223,8 +223,7 @@ struct PointerStringPairHash {
} }
// Used only by MSVC and platforms where hash_map is not available. // Used only by MSVC and platforms where hash_map is not available.
static const size_t bucket_size = 4; enum { bucket_size = 4, min_buckets = 8 };
static const size_t min_buckets = 8;
inline bool operator()(const PointerStringPair& a, inline bool operator()(const PointerStringPair& a,
const PointerStringPair& b) const { const PointerStringPair& b) const {
if (a.first < b.first) return true; if (a.first < b.first) return true;
......
...@@ -729,13 +729,6 @@ char *FastHex32ToBuffer(uint32 value, char* buffer) { ...@@ -729,13 +729,6 @@ char *FastHex32ToBuffer(uint32 value, char* buffer) {
return InternalFastHexToBuffer(value, buffer, 8); return InternalFastHexToBuffer(value, buffer, 8);
} }
static inline char* PlaceNum(char* p, int num, char prev_sep) {
*p-- = '0' + num % 10;
*p-- = '0' + num / 10;
*p-- = prev_sep;
return p;
}
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// FastInt32ToBufferLeft() // FastInt32ToBufferLeft()
// FastUInt32ToBufferLeft() // FastUInt32ToBufferLeft()
......
...@@ -53,15 +53,6 @@ namespace google { ...@@ -53,15 +53,6 @@ namespace google {
namespace protobuf { namespace protobuf {
namespace internal { namespace internal {
namespace {
// This function turns out to be convenient when using some macros later.
inline int GetEnumNumber(const EnumValueDescriptor* descriptor) {
return descriptor->number();
}
} // anonymous namespace
// =================================================================== // ===================================================================
bool UnknownFieldSetFieldSkipper::SkipField( bool UnknownFieldSetFieldSkipper::SkipField(
......
...@@ -52,12 +52,10 @@ endif() ...@@ -52,12 +52,10 @@ endif()
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# Download pre-trained models for complex testing on GoogLeNet and AlexNet # Download pre-trained models for complex testing on GoogLeNet and AlexNet
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
OCV_OPTION(${the_module}_DOWNLOAD_CAFFE_MODELS "Use GoogLeNet Caffe model for testing" OFF IF BUILD_TESTS AND PYTHON2_EXECUTABLE AND DEFINED ENV{OPENCV_TEST_DATA_PATH}) OCV_OPTION(${the_module}_DOWNLOAD_CAFFE_MODELS "Use GoogLeNet Caffe model for testing" OFF IF BUILD_TESTS AND DEFINED ENV{OPENCV_TEST_DATA_PATH})
if(BUILD_TESTS AND PYTHON2_EXECUTABLE AND DEFINED ENV{OPENCV_TEST_DATA_PATH} if(BUILD_TESTS AND DEFINED ENV{OPENCV_TEST_DATA_PATH} AND (DOWNLOAD_EXTERNAL_TEST_DATA OR ${the_module}_DOWNLOAD_CAFFE_MODELS))
AND (DOWNLOAD_EXTERNAL_TEST_DATA OR ${the_module}_DOWNLOAD_CAFFE_MODELS))
add_custom_command( TARGET opencv_test_${name} POST_BUILD add_custom_command( TARGET opencv_test_${name} POST_BUILD
COMMAND ${PYTHON2_EXECUTABLE} download_model.py test_models.json COMMAND ${CMAKE_COMMAND} -Dmodel=GoogleNet -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/download_model.cmake)
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/scripts )
add_definitions(-DENABLE_CAFFE_MODEL_TESTS=1) add_definitions(-DENABLE_CAFFE_MODEL_TESTS=1)
endif() endif()
...@@ -68,21 +66,29 @@ OCV_OPTION(${the_module}_BUILD_TORCH_IMPORTER "Build Torch model importer (exper ...@@ -68,21 +66,29 @@ OCV_OPTION(${the_module}_BUILD_TORCH_IMPORTER "Build Torch model importer (exper
if(${the_module}_BUILD_TORCH_IMPORTER) if(${the_module}_BUILD_TORCH_IMPORTER)
add_definitions(-DENABLE_TORCH_IMPORTER=1) add_definitions(-DENABLE_TORCH_IMPORTER=1)
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4702 /wd4127 /wd4267) #supress warnings in original torch files ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4702 /wd4127 /wd4267) #supress warnings in original torch files
if(NOT DEFINED HAVE_TORCH_EXE)
execute_process(COMMAND th ${CMAKE_CURRENT_SOURCE_DIR}/testdata/dnn/torch/torch_nn_echo.lua RESULT_VARIABLE TORCH_EXE_STATUS)
set(HAVE_TORCH_EXE OFF)
if(${TORCH_EXE_STATUS} EQUAL 0)
set(HAVE_TORCH_EXE ON)
endif()
set(HAVE_TORCH_EXE ${HAVE_TORCH_EXE} CACHE INTERNAL "Have torch binary")
endif()
endif() endif()
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# Generating test data for Torch importer # Generating test data for Torch importer
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
OCV_OPTION(${the_module}_BUILD_TORCH_TESTS "Build Torch tests (installed torch7 with nn module is required)" ON IF BUILD_TESTS AND ${the_module}_BUILD_TORCH_IMPORTER) OCV_OPTION(${the_module}_BUILD_TORCH_TESTS "Build Torch tests (installed torch7 with nn module is required)" ON IF BUILD_TESTS AND ${the_module}_BUILD_TORCH_IMPORTER AND HAVE_TORCH_EXE)
if(${the_module}_BUILD_TORCH_TESTS) if(${the_module}_BUILD_TORCH_TESTS)
if(NOT DEFINED ENV{OPENCV_TEST_DATA_PATH}) if(NOT DEFINED ENV{OPENCV_TEST_DATA_PATH})
message(FATAL_ERROR "OPENCV_TEST_DATA_PATH environment variable was not specified") message(FATAL_ERROR "OPENCV_TEST_DATA_PATH environment variable was not specified")
endif() endif()
execute_process(COMMAND th ${CMAKE_CURRENT_SOURCE_DIR}/testdata/dnn/torch/torch_nn_echo.lua RESULT_VARIABLE TORCH_STATUS) if(NOT HAVE_TORCH_EXE)
if(TORCH_STATUS) message(FATAL_ERROR "Torch executable \"th\" not found or nn module not found")
message(FATAL_ERROR "Torch executable \"th\" not found (status: ${TORCH_STATUS}) or nn module not found")
endif() endif()
add_custom_command( TARGET opencv_test_${name} POST_BUILD add_custom_command( TARGET opencv_test_${name} POST_BUILD
......
...@@ -23,20 +23,11 @@ else() ...@@ -23,20 +23,11 @@ else()
endif() endif()
set(PROTOBUF_LIBRARIES libprotobuf) set(PROTOBUF_LIBRARIES libprotobuf)
set(PROTOBUF_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/protobuf/src ${CMAKE_CURRENT_BINARY_DIR}) set(PROTOBUF_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/protobuf/src ${CMAKE_CURRENT_SOURCE_DIR}/misc/caffe)
set(PROTOBUF_SRCS ${CMAKE_CURRENT_BINARY_DIR}/caffe.pb.cc) set(PROTOBUF_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/misc/caffe/caffe.pb.cc)
set(PROTOBUF_HDRS ${CMAKE_CURRENT_BINARY_DIR}/caffe.pb.h) set(PROTOBUF_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/misc/caffe/caffe.pb.h)
add_definitions(-DHAVE_PROTOBUF=1) add_definitions(-DHAVE_PROTOBUF=1)
add_custom_command(
OUTPUT ${PROTOBUF_SRCS} ${PROTOBUF_HDRS}
COMMAND ${CMAKE_COMMAND} -E tar xzf ${CMAKE_CURRENT_SOURCE_DIR}/src/caffe/compiled/caffe.tar.gz
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Unpacking compiled caffe protobuf files"
VERBATIM
)
set_source_files_properties(${PROTOBUF_SRCS} ${PROTOBUF_HDRS} PROPERTIES GENERATED TRUE)
#supress warnings in autogenerated caffe.pb.* files #supress warnings in autogenerated caffe.pb.* files
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wunused-parameter) ocv_warnings_disable(CMAKE_CXX_FLAGS -Wunused-parameter)
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4125 /wd4267 /wd4127 /wd4244 /wd4512 /wd4702) ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4125 /wd4267 /wd4127 /wd4244 /wd4512 /wd4702)
......
...@@ -13,11 +13,18 @@ ...@@ -13,11 +13,18 @@
# MKL_LIBRARIES - IPP libraries that are used by OpenCV # MKL_LIBRARIES - IPP libraries that are used by OpenCV
# #
macro (mkl_find_lib VAR NAME DIRS)
find_path(${VAR} ${NAME} ${DIRS} NO_DEFAULT_PATH)
set(${VAR} ${${VAR}}/${NAME})
unset(${VAR} CACHE)
endmacro()
macro(mkl_fail) macro(mkl_fail)
set(HAVE_MKL OFF CACHE BOOL "True if MKL found") set(HAVE_MKL OFF CACHE BOOL "True if MKL found")
set(MKL_ROOT_DIR ${MKL_ROOT_DIR} CACHE PATH "Path to MKL directory") set(MKL_ROOT_DIR ${MKL_ROOT_DIR} CACHE PATH "Path to MKL directory")
unset(MKL_INCLUDE_DIRS CACHE) unset(MKL_INCLUDE_DIRS CACHE)
unset(MKL_LIBRARIES CACHE) unset(MKL_LIBRARIES CACHE)
return()
endmacro() endmacro()
macro(get_mkl_version VERSION_FILE) macro(get_mkl_version VERSION_FILE)
...@@ -42,28 +49,27 @@ endif() ...@@ -42,28 +49,27 @@ endif()
#check current MKL_ROOT_DIR #check current MKL_ROOT_DIR
if(NOT MKL_ROOT_DIR OR NOT EXISTS ${MKL_ROOT_DIR}/include/mkl.h) if(NOT MKL_ROOT_DIR OR NOT EXISTS ${MKL_ROOT_DIR}/include/mkl.h)
set(MKLROOT_PATHS ${MKL_ROOT_DIR}) set(mkl_root_paths ${MKL_ROOT_DIR})
if(DEFINED $ENV{MKLROOT}) if(DEFINED $ENV{MKLROOT})
list(APPEND MKLROOT_PATHS $ENV{MKLROOT}) list(APPEND mkl_root_paths $ENV{MKLROOT})
endif() endif()
if(WIN32) if(WIN32)
set(ProgramFilesx86 "ProgramFiles(x86)") set(ProgramFilesx86 "ProgramFiles(x86)")
list(APPEND MKLROOT_PATHS $ENV{${ProgramFilesx86}}/IntelSWTools/compilers_and_libraries/windows/mkl) list(APPEND mkl_root_paths $ENV{${ProgramFilesx86}}/IntelSWTools/compilers_and_libraries/windows/mkl)
endif() endif()
if(UNIX) if(UNIX)
list(APPEND MKLROOT_PATHS "/opt/intel/mkl") list(APPEND mkl_root_paths "/opt/intel/mkl")
endif() endif()
find_path(MKL_ROOT_DIR include/mkl.h PATHS ${MKLROOT_PATHS}) find_path(MKL_ROOT_DIR include/mkl.h PATHS ${mkl_root_paths})
endif() endif()
if(NOT MKL_ROOT_DIR) if(NOT MKL_ROOT_DIR)
mkl_fail() mkl_fail()
return()
endif() endif()
set(MKL_INCLUDE_DIRS ${MKL_ROOT_DIR}/include) set(MKL_INCLUDE_DIRS ${MKL_ROOT_DIR}/include)
set(MKL_INCLUDE_HEADERS ${MKL_INCLUDE_DIRS}/mkl.h ${MKL_INCLUDE_DIRS}/mkl_version.h) get_mkl_version(${MKL_INCLUDE_DIRS}/mkl_version.h)
#determine arch #determine arch
if(CMAKE_CXX_SIZEOF_DATA_PTR EQUAL 8) if(CMAKE_CXX_SIZEOF_DATA_PTR EQUAL 8)
...@@ -81,43 +87,50 @@ else() ...@@ -81,43 +87,50 @@ else()
set(MKL_ARCH "ia32") set(MKL_ARCH "ia32")
endif() endif()
if(MSVC) if(${MKL_VERSION_STR} VERSION_GREATER "11.3.0" OR ${MKL_VERSION_STR} VERSION_EQUAL "11.3.0")
set(MKL_EXT ".lib") set(mkl_lib_find_paths
set(MKL_PRE "") ${MKL_ROOT_DIR}/lib
else() ${MKL_ROOT_DIR}/lib/${MKL_ARCH} ${MKL_ROOT_DIR}/../tbb/lib/${MKL_ARCH})
set(MKL_EXT ".a")
set(MKL_PRE "lib") set(mkl_lib_list
endif() mkl_core
mkl_intel_${MKL_LP64})
set(MKL_LIB_DIR ${MKL_ROOT_DIR}/lib/${MKL_ARCH})
set(MKL_LIBRARIES ${MKL_LIB_DIR}/${MKL_PRE}mkl_core${MKL_EXT} ${MKL_LIB_DIR}/${MKL_PRE}mkl_intel_${MKL_LP64}${MKL_EXT}) if(MKL_WITH_TBB)
list(APPEND mkl_lib_list mkl_tbb_thread tbb)
if(MKL_WITH_TBB) elseif(MKL_WITH_OPENMP)
list(APPEND MKL_LIBRARIES ${MKL_LIB_DIR}/${MKL_PRE}mkl_tbb_thread${MKL_EXT}) if(MSVC)
list(APPEND MKL_LIBRARIES ${MKL_ROOT_DIR}/../tbb/lib/${MKL_ARCH}/tbb${MKL_EXT}) list(APPEND mkl_lib_list mkl_intel_thread libiomp5md)
elseif(MKL_WITH_OPENMP) else()
message(FATAL_ERROR "Multithreaded MKL is not supported yet") list(APPEND mkl_lib_list libmkl_gnu_thread)
endif()
else()
list(APPEND mkl_lib_list mkl_sequential)
endif()
else() else()
list(APPEND MKL_LIBRARIES ${MKL_LIB_DIR}/${MKL_PRE}mkl_sequential${MKL_EXT}) message(STATUS "MKL version ${MKL_VERSION_STR} is not supported")
mkl_fail()
endif() endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MKL MKL_INCLUDE_HEADERS MKL_LIBRARIES)
if(MKL_FOUND)
get_mkl_version(${MKL_INCLUDE_DIRS}/mkl_version.h)
message(STATUS "Found MKL ${MKL_VERSION_STR} at: ${MKL_ROOT_DIR}")
set(HAVE_MKL ON CACHE BOOL "True if MKL found") set(MKL_LIBRARIES "")
set(MKL_ROOT_DIR ${MKL_ROOT_DIR} CACHE PATH "Path to MKL directory") foreach(lib ${mkl_lib_list})
set(MKL_INCLUDE_DIRS ${MKL_INCLUDE_DIRS} CACHE PATH "Path to MKL include directory") find_library(${lib} ${lib} ${mkl_lib_find_paths})
if(NOT UNIX) mark_as_advanced(${lib})
set(MKL_LIBRARIES ${MKL_LIBRARIES} CACHE FILEPATH "MKL libarries") if(NOT ${lib})
else() mkl_fail()
#it's ugly but helps to avoid cyclic lib problem
set(MKL_LIBRARIES ${MKL_LIBRARIES} ${MKL_LIBRARIES} ${MKL_LIBRARIES} "-lpthread" "-lm" "-ldl")
set(MKL_LIBRARIES ${MKL_LIBRARIES} CACHE STRING "MKL libarries")
endif() endif()
list(APPEND MKL_LIBRARIES ${${lib}})
endforeach()
message(STATUS "Found MKL ${MKL_VERSION_STR} at: ${MKL_ROOT_DIR}")
set(HAVE_MKL ON CACHE BOOL "True if MKL found")
set(MKL_ROOT_DIR ${MKL_ROOT_DIR} CACHE PATH "Path to MKL directory")
set(MKL_INCLUDE_DIRS ${MKL_INCLUDE_DIRS} CACHE PATH "Path to MKL include directory")
if(NOT UNIX)
set(MKL_LIBRARIES ${MKL_LIBRARIES} CACHE FILEPATH "MKL libarries")
else() else()
#it's ugly but helps to avoid cyclic lib problem
set(MKL_LIBRARIES ${MKL_LIBRARIES} ${MKL_LIBRARIES} ${MKL_LIBRARIES} "-lpthread" "-lm" "-ldl")
set(MKL_LIBRARIES ${MKL_LIBRARIES} CACHE STRING "MKL libarries")
endif() endif()
\ No newline at end of file
set(GoogleNet_url "http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel")
set(GoogleNet_dst "$ENV{OPENCV_TEST_DATA_PATH}/dnn/bvlc_googlenet.caffemodel")
set(GoogleNet_sha "405fc5acd08a3bb12de8ee5e23a96bec22f08204")
set(VGG16_url "http://www.robots.ox.ac.uk/~vgg/software/very_deep/caffe/VGG_ILSVRC_16_layers.caffemodel")
set(GG16_dst "$ENV{OPENCV_TEST_DATA_PATH}/dnn/VGG_ILSVRC_16_layers.caffemodel")
set(voc-fcn32s_url "http://dl.caffe.berkeleyvision.org/fcn32s-heavy-pascal.caffemodel")
set(voc-fcn32s_dst "$ENV{OPENCV_TEST_DATA_PATH}/dnn/fcn32s-heavy-pascal.caffemodel")
if(NOT model)
set(model "GoogleNet")
endif()
message(STATUS "Downloading ${${model}_url} to ${${model}_dst}")
if(NOT EXISTS ${${model}_dst})
if(${${model}_sha})
file(DOWNLOAD ${${model}_url} ${${model}_dst} SHOW_PROGRESS EXPECTED_HASH SHA1=${${model}_sha} STATUS status_vec)
else()
file(DOWNLOAD ${${model}_url} ${${model}_dst} SHOW_PROGRESS STATUS status_vec)
endif()
list(GET status_vec 0 status)
list(GET status_vec 1 status_msg)
if(status EQUAL 0)
message(STATUS "Ok! ${status_msg}")
else()
message(STATUS "Fail! ${status_msg}")
endif()
endif()
...@@ -54,7 +54,7 @@ namespace dnn ...@@ -54,7 +54,7 @@ namespace dnn
//! @{ //! @{
/** @brief Lightweight class for storing and processing a shape of blob (or anything else). */ /** @brief Lightweight class for storing and processing a shape of blob (or anything else). */
struct BlobShape struct CV_EXPORTS_W BlobShape
{ {
BlobShape(); //!< Creates [1, 1, 1, 1] shape @todo Make more clearer behavior. BlobShape(); //!< Creates [1, 1, 1, 1] shape @todo Make more clearer behavior.
explicit BlobShape(int s0); //!< Creates 1-dim shape [@p s0] explicit BlobShape(int s0); //!< Creates 1-dim shape [@p s0]
...@@ -154,7 +154,7 @@ namespace dnn ...@@ -154,7 +154,7 @@ namespace dnn
/** @brief Constructs Blob from existing Mat or UMat. */ /** @brief Constructs Blob from existing Mat or UMat. */
Blob(InputArray data); Blob(InputArray data);
/** @brief Constucts 4-dimensional blob (so-called batch) from image or array of images. /** @brief Constructs 4-dimensional blob (so-called batch) from image or array of images.
* @param image 2-dimensional multi-channel or 3-dimensional single-channel image (or array of such images) * @param image 2-dimensional multi-channel or 3-dimensional single-channel image (or array of such images)
* @param dstCn specifies size of second axis of ouptut blob * @param dstCn specifies size of second axis of ouptut blob
*/ */
...@@ -229,6 +229,18 @@ namespace dnn ...@@ -229,6 +229,18 @@ namespace dnn
/** @brief Checks equality of two blobs shapes. */ /** @brief Checks equality of two blobs shapes. */
bool equalShape(const Blob &other) const; bool equalShape(const Blob &other) const;
/** @brief Returns slice of first two dimensions.
* @details The behaviour is similar to the following numpy code: blob[n, cn, ...]
*/
Mat getPlane(int n, int cn);
/** @brief Returns slice of first dimension.
* @details The behaviour is similar to getPlane(), but returns all
* channels * rows * cols values, corresponding to the n-th value
* of the first dimension.
*/
Mat getPlanes(int n);
/* Shape getters of 4-dimensional blobs. */ /* Shape getters of 4-dimensional blobs. */
int cols() const; //!< Returns size of the fourth axis blob. int cols() const; //!< Returns size of the fourth axis blob.
int rows() const; //!< Returns size of the thrid axis blob. int rows() const; //!< Returns size of the thrid axis blob.
...@@ -262,12 +274,6 @@ namespace dnn ...@@ -262,12 +274,6 @@ namespace dnn
float *ptrf(int n = 0, int cn = 0, int row = 0, int col = 0); float *ptrf(int n = 0, int cn = 0, int row = 0, int col = 0);
//TODO: add const ptr methods //TODO: add const ptr methods
/** @brief Returns slice of first two dimensions.
* @details The behaviour is similar to the following numpy code: blob[n, cn, ...]
* @todo Method will be removed. Use slice() from shape_utils.hpp.
*/
Mat getPlane(int n, int cn);
/** @brief Shares data from other @p blob. /** @brief Shares data from other @p blob.
* @returns *this * @returns *this
*/ */
...@@ -312,17 +318,17 @@ namespace dnn ...@@ -312,17 +318,17 @@ namespace dnn
public: public:
enum DataState enum DataState
{ {
UNINITIALIZED, UNINITIALIZED = 0,
HEAD_AT_MAT, HEAD_AT_MAT = 1 << 0,
HEAD_AT_UMAT, HEAD_AT_UMAT = 1 << 1,
SYNCED SYNCED = HEAD_AT_MAT | HEAD_AT_UMAT
}; };
enum AllocFlag enum AllocFlag
{ {
ALLOC_MAT = 1, ALLOC_MAT = HEAD_AT_MAT,
ALLOC_UMAT = 2, ALLOC_UMAT = HEAD_AT_UMAT,
ALLOC_BOTH = 3 ALLOC_BOTH = SYNCED
}; };
}; };
......
...@@ -456,6 +456,12 @@ inline Mat Blob::getPlane(int n, int cn) ...@@ -456,6 +456,12 @@ inline Mat Blob::getPlane(int n, int cn)
return Mat(dims() - 2, sizes() + 2, type(), ptr(n, cn)); return Mat(dims() - 2, sizes() + 2, type(), ptr(n, cn));
} }
inline Mat Blob::getPlanes(int n)
{
CV_Assert(dims() > 3);
return Mat(dims() - 1, sizes() + 1, type(), ptr(n));
}
inline int Blob::cols() const inline int Blob::cols() const
{ {
return xsize(3); return xsize(3);
......
...@@ -59,10 +59,12 @@ namespace dnn ...@@ -59,10 +59,12 @@ namespace dnn
struct DictValue struct DictValue
{ {
DictValue(const DictValue &r); DictValue(const DictValue &r);
DictValue(int p = 0) : type(Param::INT), pi(new AutoBuffer<int64,1>) { (*pi)[0] = p; } //!< Constructs integer scalar DictValue(int64 i = 0) : type(Param::INT), pi(new AutoBuffer<int64,1>) { (*pi)[0] = i; } //!< Constructs integer scalar
DictValue(int i) : type(Param::INT), pi(new AutoBuffer<int64,1>) { (*pi)[0] = i; } //!< Constructs integer scalar
DictValue(unsigned p) : type(Param::INT), pi(new AutoBuffer<int64,1>) { (*pi)[0] = p; } //!< Constructs integer scalar DictValue(unsigned p) : type(Param::INT), pi(new AutoBuffer<int64,1>) { (*pi)[0] = p; } //!< Constructs integer scalar
DictValue(double p) : type(Param::REAL), pd(new AutoBuffer<double,1>) { (*pd)[0] = p; } //!< Constructs floating point scalar DictValue(double p) : type(Param::REAL), pd(new AutoBuffer<double,1>) { (*pd)[0] = p; } //!< Constructs floating point scalar
DictValue(const String &p) : type(Param::STRING), ps(new AutoBuffer<String,1>) { (*ps)[0] = p; } //!< Constructs string scalar DictValue(const String &s) : type(Param::STRING), ps(new AutoBuffer<String,1>) { (*ps)[0] = s; } //!< Constructs string scalar
DictValue(const char *s) : type(Param::STRING), ps(new AutoBuffer<String,1>) { (*ps)[0] = s; } //!< @overload
template<typename TypeIter> template<typename TypeIter>
static DictValue arrayInt(TypeIter begin, int size); //!< Constructs integer array static DictValue arrayInt(TypeIter begin, int size); //!< Constructs integer array
...@@ -111,7 +113,7 @@ class CV_EXPORTS Dict ...@@ -111,7 +113,7 @@ class CV_EXPORTS Dict
public: public:
//! Checks a presence of the @p key in the dictionary. //! Checks a presence of the @p key in the dictionary.
bool has(const String &key); bool has(const String &key) const;
//! If the @p key in the dictionary then returns pointer to its value, else returns NULL. //! If the @p key in the dictionary then returns pointer to its value, else returns NULL.
DictValue *ptr(const String &key); DictValue *ptr(const String &key);
......
...@@ -86,7 +86,7 @@ namespace dnn //! This namespace is used for dnn module functionlaity. ...@@ -86,7 +86,7 @@ namespace dnn //! This namespace is used for dnn module functionlaity.
public: public:
//! List of learned parameters must be stored here to allow read them by using Net::getParam(). //! List of learned parameters must be stored here to allow read them by using Net::getParam().
std::vector<Blob> blobs; CV_PROP_RW std::vector<Blob> blobs;
/** @brief Allocates internal buffers and output blobs with respect to the shape of inputs. /** @brief Allocates internal buffers and output blobs with respect to the shape of inputs.
* @param[in] input vector of already allocated input blobs * @param[in] input vector of already allocated input blobs
...@@ -104,6 +104,18 @@ namespace dnn //! This namespace is used for dnn module functionlaity. ...@@ -104,6 +104,18 @@ namespace dnn //! This namespace is used for dnn module functionlaity.
*/ */
virtual void forward(std::vector<Blob*> &input, std::vector<Blob> &output) = 0; virtual void forward(std::vector<Blob*> &input, std::vector<Blob> &output) = 0;
/** @brief @overload */
CV_WRAP void allocate(const std::vector<Blob> &inputs, CV_OUT std::vector<Blob> &outputs);
/** @brief @overload */
CV_WRAP std::vector<Blob> allocate(const std::vector<Blob> &inputs);
/** @brief @overload */
CV_WRAP void forward(const std::vector<Blob> &inputs, CV_IN_OUT std::vector<Blob> &outputs);
/** @brief Allocates layer and computes output. */
CV_WRAP void run(const std::vector<Blob> &inputs, CV_OUT std::vector<Blob> &outputs);
/** @brief Returns index of input blob into the input array. /** @brief Returns index of input blob into the input array.
* @param inputName label of input blob * @param inputName label of input blob
* *
...@@ -116,8 +128,8 @@ namespace dnn //! This namespace is used for dnn module functionlaity. ...@@ -116,8 +128,8 @@ namespace dnn //! This namespace is used for dnn module functionlaity.
*/ */
virtual int outputNameToIndex(String outputName); virtual int outputNameToIndex(String outputName);
String name; //!< Name of the layer instance, can be used for logging or other internal purposes. CV_PROP String name; //!< Name of the layer instance, can be used for logging or other internal purposes.
String type; //!< Type name which was used for creating layer by layer factory. CV_PROP String type; //!< Type name which was used for creating layer by layer factory.
Layer(); Layer();
explicit Layer(const LayerParams &params); //!< Initializes only #name, #type and #blobs fields. explicit Layer(const LayerParams &params); //!< Initializes only #name, #type and #blobs fields.
...@@ -135,12 +147,15 @@ namespace dnn //! This namespace is used for dnn module functionlaity. ...@@ -135,12 +147,15 @@ namespace dnn //! This namespace is used for dnn module functionlaity.
* *
* This class supports reference counting of its instances, i. e. copies point to the same instance. * This class supports reference counting of its instances, i. e. copies point to the same instance.
*/ */
class CV_EXPORTS_W Net class CV_EXPORTS_W_SIMPLE Net
{ {
public: public:
Net(); //!< Default constructor. CV_WRAP Net(); //!< Default constructor.
~Net(); //!< Destructor frees the net only if there aren't references to the net anymore. CV_WRAP ~Net(); //!< Destructor frees the net only if there aren't references to the net anymore.
/** Returns true if there are no layers in the network. */
CV_WRAP bool empty() const;
/** @brief Adds new layer to the net. /** @brief Adds new layer to the net.
* @param name unique name of the adding layer. * @param name unique name of the adding layer.
...@@ -157,13 +172,18 @@ namespace dnn //! This namespace is used for dnn module functionlaity. ...@@ -157,13 +172,18 @@ namespace dnn //! This namespace is used for dnn module functionlaity.
/** @brief Converts string name of the layer to the integer identifier. /** @brief Converts string name of the layer to the integer identifier.
* @returns id of the layer, or -1 if the layer wasn't found. * @returns id of the layer, or -1 if the layer wasn't found.
*/ */
int getLayerId(const String &layer); CV_WRAP int getLayerId(const String &layer);
CV_WRAP std::vector<String> getLayerNames() const;
/** @brief Container for strings and integers. */ /** @brief Container for strings and integers. */
typedef DictValue LayerId; typedef DictValue LayerId;
/** @brief Returns pointer to layer with specified name which the network use. */
CV_WRAP Ptr<Layer> getLayer(LayerId layerId);
/** @brief Delete layer for the network (not implemented yet) */ /** @brief Delete layer for the network (not implemented yet) */
void deleteLayer(LayerId layer); CV_WRAP void deleteLayer(LayerId layer);
/** @brief Connects output of the first layer to input of the second layer. /** @brief Connects output of the first layer to input of the second layer.
* @param outPin descriptor of the first layer output. * @param outPin descriptor of the first layer output.
...@@ -178,7 +198,7 @@ namespace dnn //! This namespace is used for dnn module functionlaity. ...@@ -178,7 +198,7 @@ namespace dnn //! This namespace is used for dnn module functionlaity.
* *
* @see setNetInputs(), Layer::inputNameToIndex(), Layer::outputNameToIndex() * @see setNetInputs(), Layer::inputNameToIndex(), Layer::outputNameToIndex()
*/ */
void connect(String outPin, String inpPin); CV_WRAP void connect(String outPin, String inpPin);
/** @brief Connects #@p outNum output of the first layer to #@p inNum input of the second layer. /** @brief Connects #@p outNum output of the first layer to #@p inNum input of the second layer.
* @param outLayerId identifier of the first layer * @param outLayerId identifier of the first layer
...@@ -188,19 +208,22 @@ namespace dnn //! This namespace is used for dnn module functionlaity. ...@@ -188,19 +208,22 @@ namespace dnn //! This namespace is used for dnn module functionlaity.
*/ */
void connect(int outLayerId, int outNum, int inpLayerId, int inpNum); void connect(int outLayerId, int outNum, int inpLayerId, int inpNum);
/** @brief Sets ouputs names of the network input pseudo layer. /** @brief Sets outputs names of the network input pseudo layer.
* *
* Each net always has special own the network input pseudo layer with id=0. * Each net always has special own the network input pseudo layer with id=0.
* This layer stores the user blobs only and don't make any computations. * This layer stores the user blobs only and don't make any computations.
* In fact, this layer provides the only way to pass user data into the network. * In fact, this layer provides the only way to pass user data into the network.
* As any other layer, this layer can label its outputs and this function provides an easy way to do this. * As any other layer, this layer can label its outputs and this function provides an easy way to do this.
*/ */
void setNetInputs(const std::vector<String> &inputBlobNames); CV_WRAP void setNetInputs(const std::vector<String> &inputBlobNames);
/** @brief Initializes and allocates all layers. */
CV_WRAP void allocate();
/** @brief Runs forward pass for the whole network */ /** @brief Runs forward pass to compute output of layer @p toLayer.
void forward(); * @details By default runs forward pass for the whole network.
/** @brief Runs forward pass to compute output of layer @p toLayer */ */
void forward(LayerId toLayer); CV_WRAP void forward(LayerId toLayer = String());
/** @brief Runs forward pass to compute output of layer @p toLayer, but computations start from @p startLayer */ /** @brief Runs forward pass to compute output of layer @p toLayer, but computations start from @p startLayer */
void forward(LayerId startLayer, LayerId toLayer); void forward(LayerId startLayer, LayerId toLayer);
/** @overload */ /** @overload */
...@@ -222,12 +245,13 @@ namespace dnn //! This namespace is used for dnn module functionlaity. ...@@ -222,12 +245,13 @@ namespace dnn //! This namespace is used for dnn module functionlaity.
* @note If updating blob is not empty then @p blob must have the same shape, * @note If updating blob is not empty then @p blob must have the same shape,
* because network reshaping is not implemented yet. * because network reshaping is not implemented yet.
*/ */
void setBlob(String outputName, const Blob &blob); CV_WRAP void setBlob(String outputName, const Blob &blob);
/** @brief Returns the layer output blob. /** @brief Returns the layer output blob.
* @param outputName the descriptor of the returning layer output blob. * @param outputName the descriptor of the returning layer output blob.
* @see connect(String, String) * @see connect(String, String)
*/ */
Blob getBlob(String outputName); CV_WRAP Blob getBlob(String outputName);
/** @brief Sets the new value for the learned param of the layer. /** @brief Sets the new value for the learned param of the layer.
* @param layer name or id of the layer. * @param layer name or id of the layer.
...@@ -237,13 +261,14 @@ namespace dnn //! This namespace is used for dnn module functionlaity. ...@@ -237,13 +261,14 @@ namespace dnn //! This namespace is used for dnn module functionlaity.
* @note If shape of the new blob differs from the previous shape, * @note If shape of the new blob differs from the previous shape,
* then the following forward pass may fail. * then the following forward pass may fail.
*/ */
void setParam(LayerId layer, int numParam, const Blob &blob); CV_WRAP void setParam(LayerId layer, int numParam, const Blob &blob);
/** @brief Returns parameter blob of the layer. /** @brief Returns parameter blob of the layer.
* @param layer name or id of the layer. * @param layer name or id of the layer.
* @param numParam index of the layer parameter in the Layer::blobs array. * @param numParam index of the layer parameter in the Layer::blobs array.
* @see Layer::blobs * @see Layer::blobs
*/ */
Blob getParam(LayerId layer, int numParam = 0); CV_WRAP Blob getParam(LayerId layer, int numParam = 0);
private: private:
...@@ -252,12 +277,12 @@ namespace dnn //! This namespace is used for dnn module functionlaity. ...@@ -252,12 +277,12 @@ namespace dnn //! This namespace is used for dnn module functionlaity.
}; };
/** @brief Small interface class for loading trained serialized models of different dnn-frameworks. */ /** @brief Small interface class for loading trained serialized models of different dnn-frameworks. */
class Importer class CV_EXPORTS_W Importer
{ {
public: public:
/** @brief Adds loaded layers into the @p net and sets connetions between them. */ /** @brief Adds loaded layers into the @p net and sets connections between them. */
virtual void populateNet(Net net) = 0; CV_WRAP virtual void populateNet(Net net) = 0;
virtual ~Importer(); virtual ~Importer();
}; };
...@@ -267,7 +292,12 @@ namespace dnn //! This namespace is used for dnn module functionlaity. ...@@ -267,7 +292,12 @@ namespace dnn //! This namespace is used for dnn module functionlaity.
* @param caffeModel path to the .caffemodel file with learned network. * @param caffeModel path to the .caffemodel file with learned network.
* @returns Pointer to the created importer, NULL in failure cases. * @returns Pointer to the created importer, NULL in failure cases.
*/ */
CV_EXPORTS Ptr<Importer> createCaffeImporter(const String &prototxt, const String &caffeModel = String()); CV_EXPORTS_W Ptr<Importer> createCaffeImporter(const String &prototxt, const String &caffeModel = String());
/** @brief Reads a network model stored in Caffe model files.
* @details This is shortcut consisting from createCaffeImporter and Net::populateNet calls.
*/
CV_EXPORTS_W Net readNetFromCaffe(const String &prototxt, const String &caffeModel = String());
/** @brief Creates the importer of <a href="http://torch.ch">Torch7</a> framework network. /** @brief Creates the importer of <a href="http://torch.ch">Torch7</a> framework network.
* @param filename path to the file, dumped from Torch by using torch.save() function. * @param filename path to the file, dumped from Torch by using torch.save() function.
...@@ -294,12 +324,12 @@ namespace dnn //! This namespace is used for dnn module functionlaity. ...@@ -294,12 +324,12 @@ namespace dnn //! This namespace is used for dnn module functionlaity.
* *
* Also some equivalents of these classes from cunn, cudnn, and fbcunn may be successfully imported. * Also some equivalents of these classes from cunn, cudnn, and fbcunn may be successfully imported.
*/ */
CV_EXPORTS Ptr<Importer> createTorchImporter(const String &filename, bool isBinary = true); CV_EXPORTS_W Ptr<Importer> createTorchImporter(const String &filename, bool isBinary = true);
/** @brief Loads blob which was serialized as torch.Tensor object of Torch7 framework. /** @brief Loads blob which was serialized as torch.Tensor object of Torch7 framework.
* @warning This function has the same limitations as createTorchImporter(). * @warning This function has the same limitations as createTorchImporter().
*/ */
CV_EXPORTS Blob readTorchBlob(const String &filename, bool isBinary = true); CV_EXPORTS_W Blob readTorchBlob(const String &filename, bool isBinary = true);
//! @} //! @}
} }
......
...@@ -287,7 +287,7 @@ inline std::ostream &operator<<(std::ostream &stream, const DictValue &dictv) ...@@ -287,7 +287,7 @@ inline std::ostream &operator<<(std::ostream &stream, const DictValue &dictv)
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
inline bool Dict::has(const String &key) inline bool Dict::has(const String &key) const
{ {
return dict.count(key) != 0; return dict.count(key) != 0;
} }
......
This diff is collapsed.
This diff is collapsed.
#ifdef HAVE_OPENCV_DNN
typedef dnn::DictValue LayerId;
typedef std::vector<cv::dnn::Blob> vector_Blob;
template<>
bool pyopencv_to(PyObject *o, dnn::Blob &blob, const char *name);
template<> struct pyopencvVecConverter<dnn::Blob>
{
static bool to(PyObject* obj, std::vector<dnn::Blob>& value, const ArgInfo info)
{
if (PyArray_Check(obj))
{
value.resize(1);
return pyopencv_to(obj, value[0], info.name);
}
return pyopencv_to_generic_vec(obj, value, info);
}
static PyObject* from(const std::vector<dnn::Blob>& value)
{
return pyopencv_from_generic_vec(value);
}
};
template<>
bool pyopencv_to(PyObject *o, std::vector<dnn::Blob> &blobs, const char *name) //required for Layer::blobs RW
{
return pyopencvVecConverter<dnn::Blob>::to(o, blobs, ArgInfo(name, false));
}
template<>
bool pyopencv_to(PyObject *o, dnn::Blob &blob, const char *name)
{
Mat &dst = blob.matRef();
if (!pyopencv_to(o, dst, name))
return false;
if (PyArray_Check(o)) //try fix channels
{
PyArrayObject* oarr = (PyArrayObject*) o;
if (PyArray_NDIM(oarr) == dst.dims)
return true;
int ndims = PyArray_NDIM(oarr);
std::vector<int> shape(ndims);
const npy_intp* _sizes = PyArray_DIMS(oarr);
for (int i = 0; i < ndims; i++)
shape[i] = (int)_sizes[i];
dst = dst.reshape(1, ndims, &shape[0]);
}
return true;
}
template<>
PyObject *pyopencv_from(const dnn::Blob &blob)
{
return pyopencv_from(blob.matRefConst());
}
template<>
bool pyopencv_to(PyObject *o, dnn::DictValue &dv, const char *name)
{
(void)name;
if (!o || o == Py_None)
return true; //Current state will be used
else if (PyLong_Check(o))
{
dv = dnn::DictValue((int64)PyLong_AsLongLong(o));
return true;
}
else if (PyFloat_Check(o))
{
dv = dnn::DictValue(PyFloat_AS_DOUBLE(o));
return true;
}
else if (PyString_Check(o))
{
dv = dnn::DictValue(String(PyString_AsString(o)));
return true;
}
else
return false;
}
template<>
bool pyopencv_to(PyObject *o, dnn::BlobShape &shape, const char *name)
{
std::vector<int> data;
if (!pyopencv_to_generic_vec(o, data, ArgInfo(name, false)))
return false;
shape = data.size() ? dnn::BlobShape((int)data.size(), &data[0]) : dnn::BlobShape::empty();
return true;
}
template<>
PyObject *pyopencv_from(const dnn::BlobShape &shape)
{
std::vector<int> data(shape.ptr(), shape.ptr() + shape.dims());
return pyopencv_from_generic_vec(data);
}
#endif
\ No newline at end of file
...@@ -84,23 +84,18 @@ std::vector<String> readClassNames(const char *filename = "synset_words.txt") ...@@ -84,23 +84,18 @@ std::vector<String> readClassNames(const char *filename = "synset_words.txt")
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
cv::dnn::initModule(); //Required if OpenCV is built as static libs
String modelTxt = "bvlc_googlenet.prototxt"; String modelTxt = "bvlc_googlenet.prototxt";
String modelBin = "bvlc_googlenet.caffemodel"; String modelBin = "bvlc_googlenet.caffemodel";
String imageFile = (argc > 1) ? argv[1] : "space_shuttle.jpg"; String imageFile = (argc > 1) ? argv[1] : "space_shuttle.jpg";
//! [Create the importer of Caffe model] //! [Read and initialize network]
Ptr<dnn::Importer> importer; Net net = dnn::readNetFromCaffe(modelTxt, modelBin);
try //Try to import Caffe GoogleNet model //! [Read and initialize network]
{
importer = dnn::createCaffeImporter(modelTxt, modelBin);
}
catch (const cv::Exception &err) //Importer can throw errors, we will catch them
{
std::cerr << err.msg << std::endl;
}
//! [Create the importer of Caffe model]
if (!importer) //! [Check that network was read successfully]
if (net.empty())
{ {
std::cerr << "Can't load network by using the following files: " << std::endl; std::cerr << "Can't load network by using the following files: " << std::endl;
std::cerr << "prototxt: " << modelTxt << std::endl; std::cerr << "prototxt: " << modelTxt << std::endl;
...@@ -109,12 +104,7 @@ int main(int argc, char **argv) ...@@ -109,12 +104,7 @@ int main(int argc, char **argv)
std::cerr << "http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel" << std::endl; std::cerr << "http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel" << std::endl;
exit(-1); exit(-1);
} }
//! [Check that network was read successfully]
//! [Initialize network]
dnn::Net net;
importer->populateNet(net);
importer.release(); //We don't need importer anymore
//! [Initialize network]
//! [Prepare blob] //! [Prepare blob]
Mat img = imread(imageFile); Mat img = imread(imageFile);
......
#
# This prototxt is based on voc-fcn32s/val.prototxt file from
# https://github.com/shelhamer/fcn.berkeleyvision.org, which is distributed under
# Caffe (BSD) license:
# http://caffe.berkeleyvision.org/model_zoo.html#bvlc-model-license
#
name: "voc-fcn32s"
input: "data"
input_dim: 1
input_dim: 3
input_dim: 500
input_dim: 500
layer {
name: "conv1_1"
type: "Convolution"
bottom: "data"
top: "conv1_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 64
pad: 100
kernel_size: 3
stride: 1
}
}
layer {
name: "relu1_1"
type: "ReLU"
bottom: "conv1_1"
top: "conv1_1"
}
layer {
name: "conv1_2"
type: "Convolution"
bottom: "conv1_1"
top: "conv1_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 64
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu1_2"
type: "ReLU"
bottom: "conv1_2"
top: "conv1_2"
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1_2"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv2_1"
type: "Convolution"
bottom: "pool1"
top: "conv2_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 128
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu2_1"
type: "ReLU"
bottom: "conv2_1"
top: "conv2_1"
}
layer {
name: "conv2_2"
type: "Convolution"
bottom: "conv2_1"
top: "conv2_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 128
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu2_2"
type: "ReLU"
bottom: "conv2_2"
top: "conv2_2"
}
layer {
name: "pool2"
type: "Pooling"
bottom: "conv2_2"
top: "pool2"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv3_1"
type: "Convolution"
bottom: "pool2"
top: "conv3_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_1"
type: "ReLU"
bottom: "conv3_1"
top: "conv3_1"
}
layer {
name: "conv3_2"
type: "Convolution"
bottom: "conv3_1"
top: "conv3_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_2"
type: "ReLU"
bottom: "conv3_2"
top: "conv3_2"
}
layer {
name: "conv3_3"
type: "Convolution"
bottom: "conv3_2"
top: "conv3_3"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_3"
type: "ReLU"
bottom: "conv3_3"
top: "conv3_3"
}
layer {
name: "pool3"
type: "Pooling"
bottom: "conv3_3"
top: "pool3"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv4_1"
type: "Convolution"
bottom: "pool3"
top: "conv4_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_1"
type: "ReLU"
bottom: "conv4_1"
top: "conv4_1"
}
layer {
name: "conv4_2"
type: "Convolution"
bottom: "conv4_1"
top: "conv4_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_2"
type: "ReLU"
bottom: "conv4_2"
top: "conv4_2"
}
layer {
name: "conv4_3"
type: "Convolution"
bottom: "conv4_2"
top: "conv4_3"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_3"
type: "ReLU"
bottom: "conv4_3"
top: "conv4_3"
}
layer {
name: "pool4"
type: "Pooling"
bottom: "conv4_3"
top: "pool4"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv5_1"
type: "Convolution"
bottom: "pool4"
top: "conv5_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_1"
type: "ReLU"
bottom: "conv5_1"
top: "conv5_1"
}
layer {
name: "conv5_2"
type: "Convolution"
bottom: "conv5_1"
top: "conv5_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_2"
type: "ReLU"
bottom: "conv5_2"
top: "conv5_2"
}
layer {
name: "conv5_3"
type: "Convolution"
bottom: "conv5_2"
top: "conv5_3"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_3"
type: "ReLU"
bottom: "conv5_3"
top: "conv5_3"
}
layer {
name: "pool5"
type: "Pooling"
bottom: "conv5_3"
top: "pool5"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "fc6"
type: "Convolution"
bottom: "pool5"
top: "fc6"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 4096
pad: 0
kernel_size: 7
stride: 1
}
}
layer {
name: "relu6"
type: "ReLU"
bottom: "fc6"
top: "fc6"
}
layer {
name: "fc7"
type: "Convolution"
bottom: "fc6"
top: "fc7"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 4096
pad: 0
kernel_size: 1
stride: 1
}
}
layer {
name: "relu7"
type: "ReLU"
bottom: "fc7"
top: "fc7"
}
layer {
name: "score_fr"
type: "Convolution"
bottom: "fc7"
top: "score_fr"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 21
pad: 0
kernel_size: 1
}
}
layer {
name: "upscore"
type: "Deconvolution"
bottom: "score_fr"
top: "upscore"
param {
lr_mult: 0
}
convolution_param {
num_output: 21
bias_term: false
kernel_size: 64
stride: 32
}
}
layer {
name: "score"
type: "Crop"
bottom: "upscore"
bottom: "data"
top: "score"
crop_param {
axis: 2
offset: 19
}
}
#
# This prototxt is based on voc-fcn8s/val.prototxt file from
# https://github.com/shelhamer/fcn.berkeleyvision.org, which is distributed under
# Caffe (BSD) license:
# http://caffe.berkeleyvision.org/model_zoo.html#bvlc-model-license
#
name: "voc-fcn8s"
input: "data"
input_dim: 1
input_dim: 3
input_dim: 500
input_dim: 500
layer {
name: "conv1_1"
type: "Convolution"
bottom: "data"
top: "conv1_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 64
pad: 100
kernel_size: 3
stride: 1
}
}
layer {
name: "relu1_1"
type: "ReLU"
bottom: "conv1_1"
top: "conv1_1"
}
layer {
name: "conv1_2"
type: "Convolution"
bottom: "conv1_1"
top: "conv1_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 64
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu1_2"
type: "ReLU"
bottom: "conv1_2"
top: "conv1_2"
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1_2"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv2_1"
type: "Convolution"
bottom: "pool1"
top: "conv2_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 128
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu2_1"
type: "ReLU"
bottom: "conv2_1"
top: "conv2_1"
}
layer {
name: "conv2_2"
type: "Convolution"
bottom: "conv2_1"
top: "conv2_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 128
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu2_2"
type: "ReLU"
bottom: "conv2_2"
top: "conv2_2"
}
layer {
name: "pool2"
type: "Pooling"
bottom: "conv2_2"
top: "pool2"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv3_1"
type: "Convolution"
bottom: "pool2"
top: "conv3_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_1"
type: "ReLU"
bottom: "conv3_1"
top: "conv3_1"
}
layer {
name: "conv3_2"
type: "Convolution"
bottom: "conv3_1"
top: "conv3_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_2"
type: "ReLU"
bottom: "conv3_2"
top: "conv3_2"
}
layer {
name: "conv3_3"
type: "Convolution"
bottom: "conv3_2"
top: "conv3_3"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu3_3"
type: "ReLU"
bottom: "conv3_3"
top: "conv3_3"
}
layer {
name: "pool3"
type: "Pooling"
bottom: "conv3_3"
top: "pool3"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv4_1"
type: "Convolution"
bottom: "pool3"
top: "conv4_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_1"
type: "ReLU"
bottom: "conv4_1"
top: "conv4_1"
}
layer {
name: "conv4_2"
type: "Convolution"
bottom: "conv4_1"
top: "conv4_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_2"
type: "ReLU"
bottom: "conv4_2"
top: "conv4_2"
}
layer {
name: "conv4_3"
type: "Convolution"
bottom: "conv4_2"
top: "conv4_3"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu4_3"
type: "ReLU"
bottom: "conv4_3"
top: "conv4_3"
}
layer {
name: "pool4"
type: "Pooling"
bottom: "conv4_3"
top: "pool4"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv5_1"
type: "Convolution"
bottom: "pool4"
top: "conv5_1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_1"
type: "ReLU"
bottom: "conv5_1"
top: "conv5_1"
}
layer {
name: "conv5_2"
type: "Convolution"
bottom: "conv5_1"
top: "conv5_2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_2"
type: "ReLU"
bottom: "conv5_2"
top: "conv5_2"
}
layer {
name: "conv5_3"
type: "Convolution"
bottom: "conv5_2"
top: "conv5_3"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 512
pad: 1
kernel_size: 3
stride: 1
}
}
layer {
name: "relu5_3"
type: "ReLU"
bottom: "conv5_3"
top: "conv5_3"
}
layer {
name: "pool5"
type: "Pooling"
bottom: "conv5_3"
top: "pool5"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "fc6"
type: "Convolution"
bottom: "pool5"
top: "fc6"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 4096
pad: 0
kernel_size: 7
stride: 1
}
}
layer {
name: "relu6"
type: "ReLU"
bottom: "fc6"
top: "fc6"
}
layer {
name: "fc7"
type: "Convolution"
bottom: "fc6"
top: "fc7"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 4096
pad: 0
kernel_size: 1
stride: 1
}
}
layer {
name: "relu7"
type: "ReLU"
bottom: "fc7"
top: "fc7"
}
layer {
name: "score_fr"
type: "Convolution"
bottom: "fc7"
top: "score_fr"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 21
pad: 0
kernel_size: 1
}
}
layer {
name: "upscore2"
type: "Deconvolution"
bottom: "score_fr"
top: "upscore2"
param {
lr_mult: 0
}
convolution_param {
num_output: 21
bias_term: false
kernel_size: 4
stride: 2
}
}
layer {
name: "score_pool4"
type: "Convolution"
bottom: "pool4"
top: "score_pool4"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 21
pad: 0
kernel_size: 1
}
}
layer {
name: "score_pool4c"
type: "Crop"
bottom: "score_pool4"
bottom: "upscore2"
top: "score_pool4c"
crop_param {
axis: 2
offset: 5
}
}
layer {
name: "fuse_pool4"
type: "Eltwise"
bottom: "upscore2"
bottom: "score_pool4c"
top: "fuse_pool4"
eltwise_param {
operation: SUM
}
}
layer {
name: "upscore_pool4"
type: "Deconvolution"
bottom: "fuse_pool4"
top: "upscore_pool4"
param {
lr_mult: 0
}
convolution_param {
num_output: 21
bias_term: false
kernel_size: 4
stride: 2
}
}
layer {
name: "score_pool3"
type: "Convolution"
bottom: "pool3"
top: "score_pool3"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 21
pad: 0
kernel_size: 1
}
}
layer {
name: "score_pool3c"
type: "Crop"
bottom: "score_pool3"
bottom: "upscore_pool4"
top: "score_pool3c"
crop_param {
axis: 2
offset: 9
}
}
layer {
name: "fuse_pool3"
type: "Eltwise"
bottom: "upscore_pool4"
bottom: "score_pool3c"
top: "fuse_pool3"
eltwise_param {
operation: SUM
}
}
layer {
name: "upscore8"
type: "Deconvolution"
bottom: "fuse_pool3"
top: "upscore8"
param {
lr_mult: 0
}
convolution_param {
num_output: 21
bias_term: false
kernel_size: 16
stride: 8
}
}
layer {
name: "score"
type: "Crop"
bottom: "upscore8"
bottom: "data"
top: "score"
crop_param {
axis: 2
offset: 31
}
}
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core/ocl.hpp>
using namespace cv;
using namespace cv::dnn;
#include <fstream>
#include <iostream>
#include <cstdlib>
using namespace std;
static const string fcnType = "fcn8s";
static vector<cv::Vec3b> readColors(const string &filename = "pascal-classes.txt")
{
vector<cv::Vec3b> colors;
ifstream fp(filename.c_str());
if (!fp.is_open())
{
cerr << "File with colors not found: " << filename << endl;
exit(-1);
}
string line;
while (!fp.eof())
{
getline(fp, line);
if (line.length())
{
stringstream ss(line);
string name; ss >> name;
int temp;
cv::Vec3b color;
ss >> temp; color[0] = temp;
ss >> temp; color[1] = temp;
ss >> temp; color[2] = temp;
colors.push_back(color);
}
}
fp.close();
return colors;
}
static void colorizeSegmentation(dnn::Blob &score, const vector<cv::Vec3b> &colors, cv::Mat &segm)
{
const int rows = score.rows();
const int cols = score.cols();
const int chns = score.channels();
cv::Mat maxCl(rows, cols, CV_8UC1);
cv::Mat maxVal(rows, cols, CV_32FC1);
for (int ch = 0; ch < chns; ch++)
{
for (int row = 0; row < rows; row++)
{
const float *ptrScore = score.ptrf(0, ch, row);
uchar *ptrMaxCl = maxCl.ptr<uchar>(row);
float *ptrMaxVal = maxVal.ptr<float>(row);
for (int col = 0; col < cols; col++)
{
if (ptrScore[col] > ptrMaxVal[col])
{
ptrMaxVal[col] = ptrScore[col];
ptrMaxCl[col] = ch;
}
}
}
}
segm.create(rows, cols, CV_8UC3);
for (int row = 0; row < rows; row++)
{
const uchar *ptrMaxCl = maxCl.ptr<uchar>(row);
cv::Vec3b *ptrSegm = segm.ptr<cv::Vec3b>(row);
for (int col = 0; col < cols; col++)
{
ptrSegm[col] = colors[ptrMaxCl[col]];
}
}
}
int main(int argc, char **argv)
{
cv::dnn::initModule(); //Required if OpenCV is built as static libs
cv::ocl::setUseOpenCL(false); //OpenCL switcher
String modelTxt = fcnType + "-heavy-pascal.prototxt";
String modelBin = fcnType + "-heavy-pascal.caffemodel";
String imageFile = (argc > 1) ? argv[1] : "rgb.jpg";
vector<cv::Vec3b> colors = readColors();
//! [Create the importer of Caffe model]
Ptr<dnn::Importer> importer;
try //Try to import Caffe GoogleNet model
{
importer = dnn::createCaffeImporter(modelTxt, modelBin);
}
catch (const cv::Exception &err) //Importer can throw errors, we will catch them
{
cerr << err.msg << endl;
}
//! [Create the importer of Caffe model]
if (!importer)
{
cerr << "Can't load network by using the following files: " << endl;
cerr << "prototxt: " << modelTxt << endl;
cerr << "caffemodel: " << modelBin << endl;
cerr << fcnType << "-heavy-pascal.caffemodel can be downloaded here:" << endl;
cerr << "http://dl.caffe.berkeleyvision.org/" << fcnType << "-heavy-pascal.caffemodel" << endl;
exit(-1);
}
//! [Initialize network]
dnn::Net net;
importer->populateNet(net);
importer.release(); //We don't need importer anymore
//! [Initialize network]
//! [Prepare blob]
Mat img = imread(imageFile);
if (img.empty())
{
cerr << "Can't read image from the file: " << imageFile << endl;
exit(-1);
}
resize(img, img, Size(500, 500)); //FCN accepts 500x500 RGB-images
dnn::Blob inputBlob = dnn::Blob::fromImages(img); //Convert Mat to dnn::Blob batch of images
//! [Prepare blob]
//! [Set input blob]
net.setBlob(".data", inputBlob); //set the network input
//! [Set input blob]
//! [Make forward pass]
double t = (double)cv::getTickCount();
net.forward(); //compute output
t = (double)cv::getTickCount() - t;
printf("processing time: %.1fms\n", t*1000./getTickFrequency());
//! [Make forward pass]
//! [Gather output]
dnn::Blob score = net.getBlob("score");
cv::Mat colorize;
colorizeSegmentation(score, colors, colorize);
cv::Mat show;
cv::addWeighted(img, 0.4, colorize, 0.6, 0.0, show);
cv::imshow("show", show);
cv::waitKey(0);
return 0;
} //main
from __future__ import print_function
import numpy as np
import cv2
from cv2 import dnn
import timeit
def prepare_image(img):
img = cv2.resize(img, (224, 224))
#convert interleaved image (RGBRGB) to planar(RRGGBB)
blob = np.moveaxis(img, 2, 0)
blob = np.reshape(blob.astype(np.float32), (-1, 3, 224, 224))
return blob
def timeit_forward(net):
print("OpenCL:", cv2.ocl.useOpenCL())
print("Runtime:", timeit.timeit(lambda: net.forward(), number=10))
def get_class_list():
with open('synset_words.txt', 'rt') as f:
return [ x[x.find(" ") + 1 :] for x in f ]
blob = prepare_image(cv2.imread('space_shuttle.jpg'))
print("Input:", blob.shape, blob.dtype)
cv2.ocl.setUseOpenCL(True) #Disable OCL if you want
net = dnn.readNetFromCaffe('bvlc_googlenet.prototxt', 'bvlc_googlenet.caffemodel')
net.setBlob(".data", blob)
net.forward()
#timeit_forward(net) #Uncomment to check performance
prob = net.getBlob("prob")
print("Output:", prob.shape, prob.dtype)
classes = get_class_list()
print("Best match", classes[prob.argmax()])
\ No newline at end of file
background 0 0 0
aeroplane 128 0 0
bicycle 0 128 0
bird 128 128 0
boat 0 0 128
bottle 128 0 128
bus 0 128 128
car 128 128 128
cat 64 0 0
chair 192 0 0
cow 64 128 0
diningtable 192 128 0
dog 64 0 128
horse 192 0 128
motorbike 64 128 128
person 192 128 128
pottedplant 0 64 0
sheep 128 64 0
sofa 0 192 0
train 128 192 0
tvmonitor 0 64 128
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
using namespace cv::dnn;
#include <fstream>
#include <iostream>
#include <cstdlib>
using namespace std;
const size_t width = 300;
const size_t height = 300;
Mat getMean(const size_t& imageHeight, const size_t& imageWidth)
{
Mat mean;
const int meanValues[3] = {104, 117, 123};
vector<Mat> meanChannels;
for(size_t i = 0; i < 3; i++)
{
Mat channel(imageHeight, imageWidth, CV_32F, Scalar(meanValues[i]));
meanChannels.push_back(channel);
}
cv::merge(meanChannels, mean);
return mean;
}
Mat preprocess(const Mat& frame)
{
Mat preprocessed;
frame.convertTo(preprocessed, CV_32FC3);
resize(preprocessed, preprocessed, Size(width, height)); //SSD accepts 300x300 RGB-images
Mat mean = getMean(width, height);
cv::subtract(preprocessed, mean, preprocessed);
return preprocessed;
}
const char* about = "This sample uses Single-Shot Detector "
"(https://arxiv.org/abs/1512.02325)"
"to detect objects on image\n"; // TODO: link
const char* params
= "{ help | false | print usage }"
"{ proto | | model configuration }"
"{ model | | model weights }"
"{ image | | image for detection }"
"{ min_confidence | 0.5 | min confidence }";
int main(int argc, char** argv)
{
cv::CommandLineParser parser(argc, argv, params);
if (parser.get<bool>("help"))
{
std::cout << about << std::endl;
parser.printMessage();
return 0;
}
cv::dnn::initModule(); //Required if OpenCV is built as static libs
String modelConfiguration = parser.get<string>("proto");
String modelBinary = parser.get<string>("model");
//! [Create the importer of Caffe model]
Ptr<dnn::Importer> importer;
// Import Caffe SSD model
try
{
importer = dnn::createCaffeImporter(modelConfiguration, modelBinary);
}
catch (const cv::Exception &err) //Importer can throw errors, we will catch them
{
cerr << err.msg << endl;
}
//! [Create the importer of Caffe model]
if (!importer)
{
cerr << "Can't load network by using the following files: " << endl;
cerr << "prototxt: " << modelConfiguration << endl;
cerr << "caffemodel: " << modelBinary << endl;
cerr << "Models can be downloaded here:" << endl;
cerr << "https://github.com/weiliu89/caffe/tree/ssd#models" << endl;
exit(-1);
}
//! [Initialize network]
dnn::Net net;
importer->populateNet(net);
importer.release(); //We don't need importer anymore
//! [Initialize network]
cv::Mat frame = cv::imread(parser.get<string>("image"), -1);
//! [Prepare blob]
Mat preprocessedFrame = preprocess(frame);
dnn::Blob inputBlob = dnn::Blob::fromImages(preprocessedFrame); //Convert Mat to dnn::Blob image
//! [Prepare blob]
//! [Set input blob]
net.setBlob(".data", inputBlob); //set the network input
//! [Set input blob]
//! [Make forward pass]
net.forward(); //compute output
//! [Make forward pass]
//! [Gather output]
dnn::Blob detection = net.getBlob("detection_out");
Mat detectionMat(detection.rows(), detection.cols(), CV_32F, detection.ptrf());
float confidenceThreshold = parser.get<float>("min_confidence");
for(int i = 0; i < detectionMat.rows; i++)
{
float confidence = detectionMat.at<float>(i, 2);
if(confidence > confidenceThreshold)
{
size_t objectClass = detectionMat.at<float>(i, 1);
float xLeftBottom = detectionMat.at<float>(i, 3) * frame.cols;
float yLeftBottom = detectionMat.at<float>(i, 4) * frame.rows;
float xRightTop = detectionMat.at<float>(i, 5) * frame.cols;
float yRightTop = detectionMat.at<float>(i, 6) * frame.rows;
std::cout << "Class: " << objectClass << std::endl;
std::cout << "Confidence: " << confidence << std::endl;
std::cout << " " << xLeftBottom
<< " " << yLeftBottom
<< " " << xRightTop
<< " " << yRightTop << std::endl;
Rect object(xLeftBottom, yLeftBottom,
xRightTop - xLeftBottom,
yRightTop - yLeftBottom);
rectangle(frame, object, Scalar(0, 255, 0));
}
}
imshow("detections", frame);
waitKey();
return 0;
} // main
#!/usr/bin/env python
import os
import sys
import time
import urllib
import hashlib
import argparse
import json
def reporthook(count, block_size, total_size):
"""
From http://blog.moleculea.com/2012/10/04/urlretrieve-progres-indicator/
"""
global start_time
global prev_duration
if count == 0:
start_time = time.time()
prev_duration = -1
return
duration = max(1, time.time() - start_time)
if int(duration) == int(prev_duration):
return
progress_size = int(count * block_size)
speed = int(progress_size / (1024 * duration))
percent = int(count * block_size * 100 / total_size)
sys.stdout.write("\r...%d%%, %d MB, %d KB/s, %d seconds passed" %
(percent, progress_size / (1024 * 1024), speed, duration))
sys.stdout.flush()
prev_duration = duration
# Function for checking SHA1.
def model_checks_out(filename, sha1):
with open(filename, 'r') as f:
return hashlib.sha1(f.read()).hexdigest() == sha1
def model_download(filename, url, sha1):
# Check if model exists.
if os.path.exists(filename) and model_checks_out(filename, sha1):
print("Model {} already exists.".format(filename))
return
# Download and verify model.
urllib.urlretrieve(url, filename, reporthook)
print model_checks_out(filename, sha1)
if not model_checks_out(filename, sha1):
print("ERROR: model {} did not download correctly!".format(url))
sys.exit(1)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Downloading trained model binaries.")
parser.add_argument("download_list")
args = parser.parse_args()
test_dir = os.environ.get("OPENCV_TEST_DATA_PATH")
if not test_dir:
print "ERROR: OPENCV_TEST_DATA_PATH environment not specified"
sys.exit(1)
try:
with open(args.download_list, 'r') as f:
models_to_download = json.load(f)
except:
print "ERROR: Can't pasrse {}".format(args.download_list)
sys.exit(1)
for model_name in models_to_download:
model = models_to_download[model_name]
dst_dir = os.path.join(test_dir, os.path.dirname(model['file']))
dst_file = os.path.join(test_dir, model['file'])
if not os.path.exists(dst_dir):
print "ERROR: Can't find module testdata path '{}'".format(dst_dir)
sys.exit(1)
print "Downloading model '{}' to {} from {} ...".format(model_name, dst_file, model['url'])
model_download(dst_file, model['url'], model['sha1'])
\ No newline at end of file
{
"googlenet": {
"file": "dnn/bvlc_googlenet.caffemodel",
"url": "http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel",
"sha1": "405fc5acd08a3bb12de8ee5e23a96bec22f08204"
}
}
\ No newline at end of file
...@@ -63,16 +63,15 @@ Blob::Blob(InputArray data) ...@@ -63,16 +63,15 @@ Blob::Blob(InputArray data)
#ifndef CV_DNN_UMAT #ifndef CV_DNN_UMAT
m = data.getMat(); m = data.getMat();
#else #else
CV_Assert(data.isMat() || data.isUMat()); if (data.isUMat())
if (data.isMat())
{ {
m = data.getMat(); um = data.getUMat();
state = HEAD_AT_MAT; state = HEAD_AT_UMAT;
} }
else else
{ {
um = data.getUMat(); m = data.getMat();
state = HEAD_AT_UMAT; state = HEAD_AT_MAT;
} }
#endif #endif
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
set(the_description "Plot function for Mat data.") set(the_description "Plot function for Mat data.")
ocv_define_module(plot opencv_core opencv_highgui) ocv_define_module(plot opencv_core opencv_highgui WRAP python)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment