Merge pull request #1318 from SpecLad:wow

This commit is contained in:
Roman Donchenko 2013-08-22 11:49:43 +04:00 committed by OpenCV Buildbot
commit 43aec5ad4a
628 changed files with 2623 additions and 3042 deletions

80
.gitattributes vendored
View File

@ -1,42 +1,58 @@
.git* export-ignore
* text=auto whitespace=trailing-space,space-before-tab,-indent-with-non-tab,tab-in-indent,tabwidth=4
*.py text
*.cpp text
*.hpp text
*.cxx text
*.hxx text
*.mm text
*.c text
*.h text
*.i text
*.js text
*.java text
*.scala text
*.cu text
*.cl text
*.css_t text
*.qrc text
*.qss text
*.S text
*.rst text
*.tex text
*.sty text
.git* text export-ignore
*.aidl text
*.mk text
*.aidl text
*.appxmanifest text
*.bib text
*.c text
*.cl text
*.conf text
*.cpp text
*.css_t text
*.cu text
*.cxx text
*.def text
*.filelist text
*.h text
*.hpp text
*.htm text
*.html text
*.hxx text
*.i text
*.idl text
*.java text
*.js text
*.mk text
*.mm text
*.plist text
*.properties text
*.py text
*.qrc text
*.qss text
*.S text
*.sbt text
*.scala text
*.sty text
*.tex text
*.txt text
*.xaml text
# reST underlines/overlines can look like conflict markers
*.rst text conflict-marker-size=80
*.cmake text whitespace=tabwidth=2
*.cmakein text whitespace=tabwidth=2
*.in text whitespace=tabwidth=2
CMakeLists.txt text whitespace=tabwidth=2
*.png binary
*.jpeg binary
*.jpg binary
*.avi binary
*.bmp binary
*.exr binary
*.ico binary
*.jpeg binary
*.jpg binary
*.png binary
*.a binary
*.so binary
@ -47,6 +63,7 @@ CMakeLists.txt text whitespace=tabwidth=2
*.pbxproj binary
*.vec binary
*.doc binary
*.dia binary
*.xml -text whitespace=cr-at-eol
*.yml -text whitespace=cr-at-eol
@ -55,9 +72,12 @@ CMakeLists.txt text whitespace=tabwidth=2
.cproject -text whitespace=cr-at-eol merge=union
org.eclipse.jdt.core.prefs -text whitespace=cr-at-eol merge=union
*.vcproj text eol=crlf merge=union
*.bat text eol=crlf
*.cmd text eol=crlf
*.cmd.tmpl text eol=crlf
*.dsp text eol=crlf -whitespace
*.sln text eol=crlf -whitespace
*.vcproj text eol=crlf -whitespace merge=union
*.vcxproj text eol=crlf -whitespace merge=union
*.sh text eol=lf
*.sh text eol=lf

1
3rdparty/.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
* -whitespace

View File

@ -7,4 +7,4 @@ set(HAVE_GENTOO_FFMPEG 1)
set(ALIASOF_libavcodec_VERSION 53.61.100)
set(ALIASOF_libavformat_VERSION 53.32.100)
set(ALIASOF_libavutil_VERSION 51.35.100)
set(ALIASOF_libswscale_VERSION 2.1.100)
set(ALIASOF_libswscale_VERSION 2.1.100)

View File

@ -1,2 +1,2 @@
set path=c:\dev\msys32\bin;%path% & gcc -Wall -shared -o opencv_ffmpeg.dll -O2 -x c++ -I../include -I../include/ffmpeg_ -I../../modules/highgui/src ffopencv.c -L../lib -lavformat -lavcodec -lavdevice -lswscale -lavutil -lwsock32
set path=c:\dev\msys64\bin;%path% & gcc -m64 -Wall -shared -o opencv_ffmpeg_64.dll -O2 -x c++ -I../include -I../include/ffmpeg_ -I../../modules/highgui/src ffopencv.c -L../lib -lavformat64 -lavcodec64 -lavdevice64 -lswscale64 -lavutil64 -lavcore64 -lwsock32 -lws2_32
set path=c:\dev\msys64\bin;%path% & gcc -m64 -Wall -shared -o opencv_ffmpeg_64.dll -O2 -x c++ -I../include -I../include/ffmpeg_ -I../../modules/highgui/src ffopencv.c -L../lib -lavformat64 -lavcodec64 -lavdevice64 -lswscale64 -lavutil64 -lavcore64 -lwsock32 -lws2_32

View File

@ -16,7 +16,7 @@ How to update opencv_ffmpeg.dll and opencv_ffmpeg_64.dll when a new version of F
2. Install 64-bit MinGW. http://mingw-w64.sourceforge.net/
Let's assume, it's installed in C:\MSYS64
3. Copy C:\MSYS32\msys to C:\MSYS64\msys. Edit C:\MSYS64\msys\etc\fstab, change C:\MSYS32 to C:\MSYS64.
4. Now you have working MSYS32 and MSYS64 environments.
Launch, one by one, C:\MSYS32\msys\msys.bat and C:\MSYS64\msys\msys.bat to create your home directories.
@ -40,5 +40,3 @@ How to update opencv_ffmpeg.dll and opencv_ffmpeg_64.dll when a new version of F
8. Then, go to <opencv>\3rdparty\ffmpeg, edit make.bat
(change paths to the actual paths to your msys32 and msys64 distributions) and then run make.bat

View File

@ -48,4 +48,3 @@ endif()
if(NOT BUILD_SHARED_LIBS)
install(TARGETS ${JASPER_LIBRARY} ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT main)
endif()

View File

@ -168,4 +168,3 @@
/* Support Deflate compression */
#define ZIP_SUPPORT 1

4
3rdparty/readme.txt vendored
View File

@ -45,13 +45,13 @@ jasper-1.900.1 - JasPer is a collection of software
and manipulation of images. This software can handle image data in a
variety of formats. One such format supported by JasPer is the JPEG-2000
format defined in ISO/IEC 15444-1.
Copyright (c) 1999-2000 Image Power, Inc.
Copyright (c) 1999-2000 The University of British Columbia
Copyright (c) 2001-2003 Michael David Adams
The JasPer license can be found in src/libjasper.
OpenCV on Windows uses pre-built libjasper library
(lib/libjasper*). To get the latest source code,
please, visit the project homepage:

View File

@ -1 +1 @@
tbb*.tgz
tbb*.tgz

View File

@ -891,4 +891,3 @@ ocv_finalize_status()
if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
message(WARNING "The source directory is the same as binary directory. \"make clean\" may damage the source tree")
endif()

View File

@ -79,4 +79,3 @@ if(ENABLE_SOLUTION_FOLDERS)
set_target_properties(opencv_haartraining PROPERTIES FOLDER "applications")
set_target_properties(opencv_haartraining_engine PROPERTIES FOLDER "applications")
endif()

View File

@ -100,4 +100,3 @@ int icvGetIdxAt( CvMat* idx, int pos )
void icvSave( const CvArr* ptr, const char* filename, int line );
#endif /* __CVCOMMON_H_ */

View File

@ -376,4 +376,3 @@ int main( int argc, char* argv[] )
return 0;
}

View File

@ -34,4 +34,3 @@ if(ENABLE_SOLUTION_FOLDERS)
endif()
install(TARGETS ${the_target} RUNTIME DESTINATION bin COMPONENT main)

View File

@ -98,4 +98,3 @@ if(NOT BUILD_WITH_DEBUG_INFO AND NOT MSVC)
string(REPLACE "/Zi" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
string(REPLACE "/Zi" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
endif()

View File

@ -294,4 +294,4 @@ if(MSVC)
if(NOT ENABLE_NOISY_WARNINGS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251") #class 'std::XXX' needs to have dll-interface to be used by clients of YYY
endif()
endif()
endif()

View File

@ -156,4 +156,3 @@ else()
set(OpenCV_FOUND FALSE CACHE BOOL "" FORCE)
set(OPENCV_FOUND FALSE CACHE BOOL "" FORCE)
endif()

View File

@ -140,7 +140,7 @@ endfunction()
# ------------------------------------------------------------------------
function(set_ipp_new_libraries _LATEST_VERSION)
set(IPP_PREFIX "ipp")
if(${_LATEST_VERSION} VERSION_LESS "8.0")
set(IPP_SUFFIX "_l") # static not threaded libs suffix IPP 7.x
else()
@ -346,4 +346,4 @@ if(WIN32 AND MINGW AND NOT IPP_LATEST_VERSION_MAJOR LESS 7)
# See http://code.opencv.org/issues/1906 for additional details
set(MSV_NTDLL "ntdll")
set(IPP_LIBRARIES ${IPP_LIBRARIES} ${MSV_NTDLL}${IPP_LIB_SUFFIX})
endif()
endif()

View File

@ -19,7 +19,7 @@ set(XIMEA_LIBRARY_DIR)
if(WIN32)
# Try to find the XIMEA API path in registry.
GET_FILENAME_COMPONENT(XIMEA_PATH "[HKEY_CURRENT_USER\\Software\\XIMEA\\CamSupport\\API;Path]" ABSOLUTE)
if(EXISTS ${XIMEA_PATH})
set(XIMEA_FOUND 1)
# set LIB folders
@ -43,4 +43,4 @@ endif()
mark_as_advanced(FORCE XIMEA_FOUND)
mark_as_advanced(FORCE XIMEA_PATH)
mark_as_advanced(FORCE XIMEA_LIBRARY_DIR)
mark_as_advanced(FORCE XIMEA_LIBRARY_DIR)

View File

@ -22,4 +22,3 @@ if(DEFINED OPENCV_BUILD_3RDPARTY_LIBS)
set(BUILD_PNG ${OPENCV_BUILD_3RDPARTY_LIBS} CACHE BOOL "Set via depricated OPENCV_BUILD_3RDPARTY_LIBS" FORCE)
unset(OPENCV_BUILD_3RDPARTY_LIBS CACHE)
endif()

View File

@ -515,4 +515,4 @@ function(ocv_source_group group)
cmake_parse_arguments(OCV_SOURCE_GROUP "" "" "GLOB" ${ARGN})
file(GLOB srcs ${OCV_SOURCE_GROUP_GLOB})
source_group(${group} FILES ${srcs})
endfunction()
endfunction()

View File

@ -11,4 +11,4 @@ int main()
printf("%d.%d ", prop.major, prop.minor);
}
return 0;
}
}

View File

@ -7,4 +7,4 @@ int main()
AVIFileInit();
AVIFileExit();
return 0;
}
}

View File

@ -2,10 +2,10 @@
int main(int argc, char** argv)
{
CreateWindow(NULL /*lpClassName*/, NULL /*lpWindowName*/, 0 /*dwStyle*/, 0 /*x*/,
0 /*y*/, 0 /*nWidth*/, 0 /*nHeight*/, NULL /*hWndParent*/, NULL /*hMenu*/,
NULL /*hInstance*/, NULL /*lpParam*/);
DeleteDC(NULL);
CreateWindow(NULL /*lpClassName*/, NULL /*lpWindowName*/, 0 /*dwStyle*/, 0 /*x*/,
0 /*y*/, 0 /*nWidth*/, 0 /*nHeight*/, NULL /*hWndParent*/, NULL /*hMenu*/,
NULL /*hInstance*/, NULL /*lpParam*/);
DeleteDC(NULL);
return 0;
return 0;
}

View File

@ -2,5 +2,5 @@
int main(int, char**)
{
return 0;
}
return 0;
}

View File

@ -32,4 +32,4 @@ foreach(cl ${cl_list})
file(APPEND ${OUTPUT} "const char* ${cl_filename}=\"${lines};\n")
endforeach()
file(APPEND ${OUTPUT} "}\n}\n")
file(APPEND ${OUTPUT} "}\n}\n")

View File

@ -23,5 +23,3 @@ FOREACH(file ${files})
MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
ENDIF(EXISTS "$ENV{DESTDIR}${file}")
ENDFOREACH(file)

View File

@ -163,4 +163,3 @@
/* Define to 1 if your processor stores words with the most significant byte
first (like Motorola and SPARC, unlike Intel and VAX). */
#cmakedefine WORDS_BIGENDIAN

View File

@ -6,4 +6,4 @@
*
*/
@OPENCV_MODULE_DEFINITIONS_CONFIGMAKE@
@OPENCV_MODULE_DEFINITIONS_CONFIGMAKE@

View File

@ -122,4 +122,4 @@ if(BUILD_DOCS AND HAVE_SPHINX)
install(FILES "${f}" DESTINATION "${OPENCV_DOC_INSTALL_PATH}" OPTIONAL)
endforeach()
endif()
endif()

View File

@ -1,4 +1,4 @@
function insertIframe (elementId, iframeSrc)
function insertIframe (elementId, iframeSrc)
{
var iframe;
if (document.createElement && (iframe = document.createElement('iframe')))
@ -10,4 +10,3 @@ function insertIframe (elementId, iframeSrc)
element.parentNode.replaceChild(iframe, element);
}
}

View File

@ -402,4 +402,4 @@ div.sphinxsidebar #searchbox input[type="text"] {
div.sphinxsidebar #searchbox input[type="submit"] {
width:auto;
}
}

View File

@ -28,4 +28,4 @@ feedbacklinkcolor = #ffffff
bodyfont = sans-serif
headfont = 'Trebuchet MS', sans-serif
guifont = "Lucida Sans","Lucida Sans Unicode","Lucida Grande",Verdana,Arial,Helvetica,sans-serif
lang = none
lang = none

View File

@ -184,5 +184,3 @@ p = RSTParser()
for m in opencv_module_list:
print "\n\n*************************** " + m + " *************************\n"
p.check_module_docs(m)

View File

@ -39,4 +39,3 @@
#7 & #8 & #9
\end{bmatrix}
}

View File

@ -75,11 +75,11 @@
% if using A4 paper. (This probably isn't strictly necessary.)
% If using another size paper, use default 1cm margins.
\ifthenelse{\lengthtest { \paperwidth = 11in}}
{ \geometry{top=.5in,left=.5in,right=.5in,bottom=.5in} }
{\ifthenelse{ \lengthtest{ \paperwidth = 297mm}}
{\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} }
{\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} }
}
{ \geometry{top=.5in,left=.5in,right=.5in,bottom=.5in} }
{\ifthenelse{ \lengthtest{ \paperwidth = 297mm}}
{\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} }
{\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} }
}
% Turn off header and footer
% \pagestyle{empty}

View File

@ -4,14 +4,14 @@ INSTRUCTIONS TO BUILD WIN32 PACKAGES WITH CMAKE+CPACK
- Install NSIS.
- Generate OpenCV solutions for MSVC using CMake as usual.
- In cmake-gui:
- In cmake-gui:
- Mark BUILD_PACKAGE
- Mark BUILD_EXAMPLES (If examples are desired to be shipped as binaries...)
- Unmark ENABLE_OPENMP, since this feature seems to have some issues yet...
- Mark INSTALL_*_EXAMPLES
- Open the OpenCV solution and build ALL in Debug and Release.
- Build PACKAGE, from the Release configuration. An NSIS installer package will be
- Build PACKAGE, from the Release configuration. An NSIS installer package will be
created with both release and debug LIBs and DLLs.
Jose Luis Blanco, 2009/JUL/29

View File

@ -3667,4 +3667,3 @@ class YErrorBars:
output.append(LineAxis(x, start, x, end, start, end, bars, False, False, **self.attr).SVG(trans))
return output

View File

@ -3,30 +3,30 @@
Camera calibration With OpenCV
******************************
Cameras have been around for a long-long time. However, with the introduction of the cheap *pinhole* cameras in the late 20th century, they became a common occurrence in our everyday life. Unfortunately, this cheapness comes with its price: significant distortion. Luckily, these are constants and with a calibration and some remapping we can correct this. Furthermore, with calibration you may also determine the relation between the camera's natural units (pixels) and the real world units (for example millimeters).
Cameras have been around for a long-long time. However, with the introduction of the cheap *pinhole* cameras in the late 20th century, they became a common occurrence in our everyday life. Unfortunately, this cheapness comes with its price: significant distortion. Luckily, these are constants and with a calibration and some remapping we can correct this. Furthermore, with calibration you may also determine the relation between the camera's natural units (pixels) and the real world units (for example millimeters).
Theory
======
For the distortion OpenCV takes into account the radial and tangential factors. For the radial factor one uses the following formula:
For the distortion OpenCV takes into account the radial and tangential factors. For the radial factor one uses the following formula:
.. math::
.. math::
x_{corrected} = x( 1 + k_1 r^2 + k_2 r^4 + k_3 r^6) \\
y_{corrected} = y( 1 + k_1 r^2 + k_2 r^4 + k_3 r^6)
So for an old pixel point at :math:`(x,y)` coordinates in the input image, its position on the corrected output image will be :math:`(x_{corrected} y_{corrected})`. The presence of the radial distortion manifests in form of the "barrel" or "fish-eye" effect.
So for an old pixel point at :math:`(x,y)` coordinates in the input image, its position on the corrected output image will be :math:`(x_{corrected} y_{corrected})`. The presence of the radial distortion manifests in form of the "barrel" or "fish-eye" effect.
Tangential distortion occurs because the image taking lenses are not perfectly parallel to the imaging plane. It can be corrected via the formulas:
Tangential distortion occurs because the image taking lenses are not perfectly parallel to the imaging plane. It can be corrected via the formulas:
.. math::
.. math::
x_{corrected} = x + [ 2p_1xy + p_2(r^2+2x^2)] \\
y_{corrected} = y + [ p_1(r^2+ 2y^2)+ 2p_2xy]
So we have five distortion parameters which in OpenCV are presented as one row matrix with 5 columns:
So we have five distortion parameters which in OpenCV are presented as one row matrix with 5 columns:
.. math::
.. math::
Distortion_{coefficients}=(k_1 \hspace{10pt} k_2 \hspace{10pt} p_1 \hspace{10pt} p_2 \hspace{10pt} k_3)
@ -38,7 +38,7 @@ Now for the unit conversion we use the following formula:
Here the presence of :math:`w` is explained by the use of homography coordinate system (and :math:`w=Z`). The unknown parameters are :math:`f_x` and :math:`f_y` (camera focal lengths) and :math:`(c_x, c_y)` which are the optical centers expressed in pixels coordinates. If for both axes a common focal length is used with a given :math:`a` aspect ratio (usually 1), then :math:`f_y=f_x*a` and in the upper formula we will have a single focal length :math:`f`. The matrix containing these four parameters is referred to as the *camera matrix*. While the distortion coefficients are the same regardless of the camera resolutions used, these should be scaled along with the current resolution from the calibrated resolution.
The process of determining these two matrices is the calibration. Calculation of these parameters is done through basic geometrical equations. The equations used depend on the chosen calibrating objects. Currently OpenCV supports three types of objects for calibration:
The process of determining these two matrices is the calibration. Calculation of these parameters is done through basic geometrical equations. The equations used depend on the chosen calibrating objects. Currently OpenCV supports three types of objects for calibration:
.. container:: enumeratevisibleitemswithsquare
@ -51,7 +51,7 @@ Basically, you need to take snapshots of these patterns with your camera and let
Goal
====
The sample application will:
The sample application will:
.. container:: enumeratevisibleitemswithsquare
@ -67,7 +67,7 @@ Source code
You may also find the source code in the :file:`samples/cpp/tutorial_code/calib3d/camera_calibration/` folder of the OpenCV source library or :download:`download it from here <../../../../samples/cpp/tutorial_code/calib3d/camera_calibration/camera_calibration.cpp>`. The program has a single argument: the name of its configuration file. If none is given then it will try to open the one named "default.xml". :download:`Here's a sample configuration file <../../../../samples/cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml>` in XML format. In the configuration file you may choose to use camera as an input, a video file or an image list. If you opt for the last one, you will need to create a configuration file where you enumerate the images to use. Here's :download:`an example of this <../../../../samples/cpp/tutorial_code/calib3d/camera_calibration/VID5.xml>`. The important part to remember is that the images need to be specified using the absolute path or the relative one from your application's working directory. You may find all this in the samples directory mentioned above.
The application starts up with reading the settings from the configuration file. Although, this is an important part of it, it has nothing to do with the subject of this tutorial: *camera calibration*. Therefore, I've chosen not to post the code for that part here. Technical background on how to do this you can find in the :ref:`fileInputOutputXMLYAML` tutorial.
The application starts up with reading the settings from the configuration file. Although, this is an important part of it, it has nothing to do with the subject of this tutorial: *camera calibration*. Therefore, I've chosen not to post the code for that part here. Technical background on how to do this you can find in the :ref:`fileInputOutputXMLYAML` tutorial.
Explanation
===========
@ -76,15 +76,15 @@ Explanation
.. code-block:: cpp
Settings s;
Settings s;
const string inputSettingsFile = argc > 1 ? argv[1] : "default.xml";
FileStorage fs(inputSettingsFile, FileStorage::READ); // Read the settings
if (!fs.isOpened())
{
cout << "Could not open the configuration file: \"" << inputSettingsFile << "\"" << endl;
cout << "Could not open the configuration file: \"" << inputSettingsFile << "\"" << endl;
return -1;
}
fs["Settings"] >> s;
fs["Settings"] >> s;
fs.release(); // close Settings file
if (!s.goodInput)
@ -95,7 +95,7 @@ Explanation
For this I've used simple OpenCV class input operation. After reading the file I've an additional post-processing function that checks validity of the input. Only if all inputs are good then *goodInput* variable will be true.
#. **Get next input, if it fails or we have enough of them - calibrate**. After this we have a big loop where we do the following operations: get the next image from the image list, camera or video file. If this fails or we have enough images then we run the calibration process. In case of image we step out of the loop and otherwise the remaining frames will be undistorted (if the option is set) via changing from *DETECTION* mode to the *CALIBRATED* one.
#. **Get next input, if it fails or we have enough of them - calibrate**. After this we have a big loop where we do the following operations: get the next image from the image list, camera or video file. If this fails or we have enough images then we run the calibration process. In case of image we step out of the loop and otherwise the remaining frames will be undistorted (if the option is set) via changing from *DETECTION* mode to the *CALIBRATED* one.
.. code-block:: cpp
@ -123,7 +123,7 @@ Explanation
if( s.flipVertical ) flip( view, view, 0 );
}
For some cameras we may need to flip the input image. Here we do this too.
For some cameras we may need to flip the input image. Here we do this too.
#. **Find the pattern in the current input**. The formation of the equations I mentioned above aims to finding major patterns in the input: in case of the chessboard this are corners of the squares and for the circles, well, the circles themselves. The position of these will form the result which will be written into the *pointBuf* vector.
@ -146,19 +146,19 @@ Explanation
break;
}
Depending on the type of the input pattern you use either the :calib3d:`findChessboardCorners <findchessboardcorners>` or the :calib3d:`findCirclesGrid <findcirclesgrid>` function. For both of them you pass the current image and the size of the board and you'll get the positions of the patterns. Furthermore, they return a boolean variable which states if the pattern was found in the input (we only need to take into account those images where this is true!).
Depending on the type of the input pattern you use either the :calib3d:`findChessboardCorners <findchessboardcorners>` or the :calib3d:`findCirclesGrid <findcirclesgrid>` function. For both of them you pass the current image and the size of the board and you'll get the positions of the patterns. Furthermore, they return a boolean variable which states if the pattern was found in the input (we only need to take into account those images where this is true!).
Then again in case of cameras we only take camera images when an input delay time is passed. This is done in order to allow user moving the chessboard around and getting different images. Similar images result in similar equations, and similar equations at the calibration step will form an ill-posed problem, so the calibration will fail. For square images the positions of the corners are only approximate. We may improve this by calling the :feature2d:`cornerSubPix <cornersubpix>` function. It will produce better calibration result. After this we add a valid inputs result to the *imagePoints* vector to collect all of the equations into a single container. Finally, for visualization feedback purposes we will draw the found points on the input image using :calib3d:`findChessboardCorners <drawchessboardcorners>` function.
Then again in case of cameras we only take camera images when an input delay time is passed. This is done in order to allow user moving the chessboard around and getting different images. Similar images result in similar equations, and similar equations at the calibration step will form an ill-posed problem, so the calibration will fail. For square images the positions of the corners are only approximate. We may improve this by calling the :feature2d:`cornerSubPix <cornersubpix>` function. It will produce better calibration result. After this we add a valid inputs result to the *imagePoints* vector to collect all of the equations into a single container. Finally, for visualization feedback purposes we will draw the found points on the input image using :calib3d:`findChessboardCorners <drawchessboardcorners>` function.
.. code-block:: cpp
if ( found) // If done with success,
if ( found) // If done with success,
{
// improve the found corners' coordinate accuracy for chessboard
if( s.calibrationPattern == Settings::CHESSBOARD)
if( s.calibrationPattern == Settings::CHESSBOARD)
{
Mat viewGray;
cvtColor(view, viewGray, CV_BGR2GRAY);
cvtColor(view, viewGray, CV_BGR2GRAY);
cornerSubPix( viewGray, pointBuf, Size(11,11),
Size(-1,-1), TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 ));
}
@ -171,11 +171,11 @@ Explanation
blinkOutput = s.inputCapture.isOpened();
}
// Draw the corners.
// Draw the corners.
drawChessboardCorners( view, s.boardSize, Mat(pointBuf), found );
}
#. **Show state and result to the user, plus command line control of the application**. This part shows text output on the image.
#. **Show state and result to the user, plus command line control of the application**. This part shows text output on the image.
.. code-block:: cpp
@ -183,7 +183,7 @@ Explanation
string msg = (mode == CAPTURING) ? "100/100" :
mode == CALIBRATED ? "Calibrated" : "Press 'g' to start";
int baseLine = 0;
Size textSize = getTextSize(msg, 1, 1, 1, &baseLine);
Size textSize = getTextSize(msg, 1, 1, 1, &baseLine);
Point textOrigin(view.cols - 2*textSize.width - 10, view.rows - 2*baseLine - 10);
if( mode == CAPTURING )
@ -199,7 +199,7 @@ Explanation
if( blinkOutput )
bitwise_not(view, view);
If we ran calibration and got camera's matrix with the distortion coefficients we may want to correct the image using :imgproc_geometric:`undistort <undistort>` function:
If we ran calibration and got camera's matrix with the distortion coefficients we may want to correct the image using :imgproc_geometric:`undistort <undistort>` function:
.. code-block:: cpp
@ -229,7 +229,7 @@ Explanation
imagePoints.clear();
}
#. **Show the distortion removal for the images too**. When you work with an image list it is not possible to remove the distortion inside the loop. Therefore, you must do this after the loop. Taking advantage of this now I'll expand the :imgproc_geometric:`undistort <undistort>` function, which is in fact first calls :imgproc_geometric:`initUndistortRectifyMap <initundistortrectifymap>` to find transformation matrices and then performs transformation using :imgproc_geometric:`remap <remap>` function. Because, after successful calibration map calculation needs to be done only once, by using this expanded form you may speed up your application:
#. **Show the distortion removal for the images too**. When you work with an image list it is not possible to remove the distortion inside the loop. Therefore, you must do this after the loop. Taking advantage of this now I'll expand the :imgproc_geometric:`undistort <undistort>` function, which is in fact first calls :imgproc_geometric:`initUndistortRectifyMap <initundistortrectifymap>` to find transformation matrices and then performs transformation using :imgproc_geometric:`remap <remap>` function. Because, after successful calibration map calculation needs to be done only once, by using this expanded form you may speed up your application:
.. code-block:: cpp
@ -256,9 +256,9 @@ Explanation
The calibration and save
========================
Because the calibration needs to be done only once per camera, it makes sense to save it after a successful calibration. This way later on you can just load these values into your program. Due to this we first make the calibration, and if it succeeds we save the result into an OpenCV style XML or YAML file, depending on the extension you give in the configuration file.
Because the calibration needs to be done only once per camera, it makes sense to save it after a successful calibration. This way later on you can just load these values into your program. Due to this we first make the calibration, and if it succeeds we save the result into an OpenCV style XML or YAML file, depending on the extension you give in the configuration file.
Therefore in the first function we just split up these two processes. Because we want to save many of the calibration variables we'll create these variables here and pass on both of them to the calibration and saving function. Again, I'll not show the saving part as that has little in common with the calibration. Explore the source file in order to find out how and what:
Therefore in the first function we just split up these two processes. Because we want to save many of the calibration variables we'll create these variables here and pass on both of them to the calibration and saving function. Again, I'll not show the saving part as that has little in common with the calibration. Explore the source file in order to find out how and what:
.. code-block:: cpp
@ -269,10 +269,10 @@ Therefore in the first function we just split up these two processes. Because we
vector<float> reprojErrs;
double totalAvgErr = 0;
bool ok = runCalibration(s,imageSize, cameraMatrix, distCoeffs, imagePoints, rvecs, tvecs,
bool ok = runCalibration(s,imageSize, cameraMatrix, distCoeffs, imagePoints, rvecs, tvecs,
reprojErrs, totalAvgErr);
cout << (ok ? "Calibration succeeded" : "Calibration failed")
<< ". avg re projection error = " << totalAvgErr ;
<< ". avg re projection error = " << totalAvgErr ;
if( ok ) // save only if the calibration was done with success
saveCameraParams( s, imageSize, cameraMatrix, distCoeffs, rvecs ,tvecs, reprojErrs,
@ -280,15 +280,15 @@ Therefore in the first function we just split up these two processes. Because we
return ok;
}
We do the calibration with the help of the :calib3d:`calibrateCamera <calibratecamera>` function. It has the following parameters:
We do the calibration with the help of the :calib3d:`calibrateCamera <calibratecamera>` function. It has the following parameters:
.. container:: enumeratevisibleitemswithsquare
+ The object points. This is a vector of *Point3f* vector that for each input image describes how should the pattern look. If we have a planar pattern (like a chessboard) then we can simply set all Z coordinates to zero. This is a collection of the points where these important points are present. Because, we use a single pattern for all the input images we can calculate this just once and multiply it for all the other input views. We calculate the corner points with the *calcBoardCornerPositions* function as:
+ The object points. This is a vector of *Point3f* vector that for each input image describes how should the pattern look. If we have a planar pattern (like a chessboard) then we can simply set all Z coordinates to zero. This is a collection of the points where these important points are present. Because, we use a single pattern for all the input images we can calculate this just once and multiply it for all the other input views. We calculate the corner points with the *calcBoardCornerPositions* function as:
.. code-block:: cpp
void calcBoardCornerPositions(Size boardSize, float squareSize, vector<Point3f>& corners,
void calcBoardCornerPositions(Size boardSize, float squareSize, vector<Point3f>& corners,
Settings::Pattern patternType /*= Settings::CHESSBOARD*/)
{
corners.clear();
@ -310,19 +310,19 @@ We do the calibration with the help of the :calib3d:`calibrateCamera <calibratec
}
}
And then multiply it as:
And then multiply it as:
.. code-block:: cpp
.. code-block:: cpp
vector<vector<Point3f> > objectPoints(1);
calcBoardCornerPositions(s.boardSize, s.squareSize, objectPoints[0], s.calibrationPattern);
objectPoints.resize(imagePoints.size(),objectPoints[0]);
objectPoints.resize(imagePoints.size(),objectPoints[0]);
+ The image points. This is a vector of *Point2f* vector which for each input image contains coordinates of the important points (corners for chessboard and centers of the circles for the circle pattern). We have already collected this from :calib3d:`findChessboardCorners <findchessboardcorners>` or :calib3d:`findCirclesGrid <findcirclesgrid>` function. We just need to pass it on.
+ The image points. This is a vector of *Point2f* vector which for each input image contains coordinates of the important points (corners for chessboard and centers of the circles for the circle pattern). We have already collected this from :calib3d:`findChessboardCorners <findchessboardcorners>` or :calib3d:`findCirclesGrid <findcirclesgrid>` function. We just need to pass it on.
+ The size of the image acquired from the camera, video file or the images.
+ The size of the image acquired from the camera, video file or the images.
+ The camera matrix. If we used the fixed aspect ratio option we need to set the :math:`f_x` to zero:
+ The camera matrix. If we used the fixed aspect ratio option we need to set the :math:`f_x` to zero:
.. code-block:: cpp
@ -330,24 +330,24 @@ We do the calibration with the help of the :calib3d:`calibrateCamera <calibratec
if( s.flag & CV_CALIB_FIX_ASPECT_RATIO )
cameraMatrix.at<double>(0,0) = 1.0;
+ The distortion coefficient matrix. Initialize with zero.
+ The distortion coefficient matrix. Initialize with zero.
.. code-block:: cpp
distCoeffs = Mat::zeros(8, 1, CV_64F);
+ For all the views the function will calculate rotation and translation vectors which transform the object points (given in the model coordinate space) to the image points (given in the world coordinate space). The 7-th and 8-th parameters are the output vector of matrices containing in the i-th position the rotation and translation vector for the i-th object point to the i-th image point.
+ For all the views the function will calculate rotation and translation vectors which transform the object points (given in the model coordinate space) to the image points (given in the world coordinate space). The 7-th and 8-th parameters are the output vector of matrices containing in the i-th position the rotation and translation vector for the i-th object point to the i-th image point.
+ The final argument is the flag. You need to specify here options like fix the aspect ratio for the focal length, assume zero tangential distortion or to fix the principal point.
+ The final argument is the flag. You need to specify here options like fix the aspect ratio for the focal length, assume zero tangential distortion or to fix the principal point.
.. code-block:: cpp
double rms = calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix,
distCoeffs, rvecs, tvecs, s.flag|CV_CALIB_FIX_K4|CV_CALIB_FIX_K5);
+ The function returns the average re-projection error. This number gives a good estimation of precision of the found parameters. This should be as close to zero as possible. Given the intrinsic, distortion, rotation and translation matrices we may calculate the error for one view by using the :calib3d:`projectPoints <projectpoints>` to first transform the object point to image point. Then we calculate the absolute norm between what we got with our transformation and the corner/circle finding algorithm. To find the average error we calculate the arithmetical mean of the errors calculated for all the calibration images.
+ The function returns the average re-projection error. This number gives a good estimation of precision of the found parameters. This should be as close to zero as possible. Given the intrinsic, distortion, rotation and translation matrices we may calculate the error for one view by using the :calib3d:`projectPoints <projectpoints>` to first transform the object point to image point. Then we calculate the absolute norm between what we got with our transformation and the corner/circle finding algorithm. To find the average error we calculate the arithmetical mean of the errors calculated for all the calibration images.
.. code-block:: cpp
.. code-block:: cpp
double computeReprojectionErrors( const vector<vector<Point3f> >& objectPoints,
const vector<vector<Point2f> >& imagePoints,
@ -378,7 +378,7 @@ We do the calibration with the help of the :calib3d:`calibrateCamera <calibratec
Results
=======
Let there be :download:`this input chessboard pattern <../../../pattern.png>` which has a size of 9 X 6. I've used an AXIS IP camera to create a couple of snapshots of the board and saved it into VID5 directory. I've put this inside the :file:`images/CameraCalibration` folder of my working directory and created the following :file:`VID5.XML` file that describes which images to use:
Let there be :download:`this input chessboard pattern <../../../pattern.png>` which has a size of 9 X 6. I've used an AXIS IP camera to create a couple of snapshots of the board and saved it into VID5 directory. I've put this inside the :file:`images/CameraCalibration` folder of my working directory and created the following :file:`VID5.XML` file that describes which images to use:
.. code-block:: xml
@ -396,25 +396,25 @@ Let there be :download:`this input chessboard pattern <../../../pattern.png>` wh
</images>
</opencv_storage>
Then passed :file:`images/CameraCalibration/VID5/VID5.XML` as an input in the configuration file. Here's a chessboard pattern found during the runtime of the application:
Then passed :file:`images/CameraCalibration/VID5/VID5.XML` as an input in the configuration file. Here's a chessboard pattern found during the runtime of the application:
.. image:: images/fileListImage.jpg
.. image:: images/fileListImage.jpg
:alt: A found chessboard
:align: center
After applying the distortion removal we get:
After applying the distortion removal we get:
.. image:: images/fileListImageUnDist.jpg
.. image:: images/fileListImageUnDist.jpg
:alt: Distortion removal for File List
:align: center
The same works for :download:`this asymmetrical circle pattern <../../../acircles_pattern.png>` by setting the input width to 4 and height to 11. This time I've used a live camera feed by specifying its ID ("1") for the input. Here's, how a detected pattern should look:
The same works for :download:`this asymmetrical circle pattern <../../../acircles_pattern.png>` by setting the input width to 4 and height to 11. This time I've used a live camera feed by specifying its ID ("1") for the input. Here's, how a detected pattern should look:
.. image:: images/asymetricalPattern.jpg
.. image:: images/asymetricalPattern.jpg
:alt: Asymmetrical circle detection
:align: center
In both cases in the specified output XML/YAML file you'll find the camera and distortion coefficients matrices:
In both cases in the specified output XML/YAML file you'll find the camera and distortion coefficients matrices:
.. code-block:: cpp
@ -433,9 +433,9 @@ In both cases in the specified output XML/YAML file you'll find the camera and d
-4.1802327176423804e-001 5.0715244063187526e-001 0. 0.
-5.7843597214487474e-001</data></Distortion_Coefficients>
Add these values as constants to your program, call the :imgproc_geometric:`initUndistortRectifyMap <initundistortrectifymap>` and the :imgproc_geometric:`remap <remap>` function to remove distortion and enjoy distortion free inputs for cheap and low quality cameras.
Add these values as constants to your program, call the :imgproc_geometric:`initUndistortRectifyMap <initundistortrectifymap>` and the :imgproc_geometric:`remap <remap>` function to remove distortion and enjoy distortion free inputs for cheap and low quality cameras.
You may observe a runtime instance of this on the `YouTube here <https://www.youtube.com/watch?v=ViPN810E0SU>`_.
You may observe a runtime instance of this on the `YouTube here <https://www.youtube.com/watch?v=ViPN810E0SU>`_.
.. raw:: html

View File

@ -7,16 +7,16 @@ Camera calibration with square chessboard
The goal of this tutorial is to learn how to calibrate a camera given a set of chessboard images.
*Test data*: use images in your data/chess folder.
*Test data*: use images in your data/chess folder.
#.
Compile opencv with samples by setting ``BUILD_EXAMPLES`` to ``ON`` in cmake configuration.
Compile opencv with samples by setting ``BUILD_EXAMPLES`` to ``ON`` in cmake configuration.
#.
Go to ``bin`` folder and use ``imagelist_creator`` to create an ``XML/YAML`` list of your images.
#.
Then, run ``calibration`` sample to get camera parameters. Use square size equal to 3cm.
Then, run ``calibration`` sample to get camera parameters. Use square size equal to 3cm.
Pose estimation
===============
@ -57,6 +57,6 @@ Now, let us write a code that detects a chessboard in a new image and finds its
distCoeffs, rvec, tvec, false);
#.
Calculate reprojection error like it is done in ``calibration`` sample (see ``opencv/samples/cpp/calibration.cpp``, function ``computeReprojectionErrors``).
Calculate reprojection error like it is done in ``calibration`` sample (see ``opencv/samples/cpp/calibration.cpp``, function ``computeReprojectionErrors``).
Question: how to calculate the distance from the camera origin to any of the corners?
Question: how to calculate the distance from the camera origin to any of the corners?

View File

@ -3,11 +3,11 @@
*calib3d* module. Camera calibration and 3D reconstruction
-----------------------------------------------------------
Although we got most of our images in a 2D format they do come from a 3D world. Here you will learn how to find out from the 2D images information about the 3D world.
Although we got most of our images in a 2D format they do come from a 3D world. Here you will learn how to find out from the 2D images information about the 3D world.
.. include:: ../../definitions/tocDefinitions.rst
.. include:: ../../definitions/tocDefinitions.rst
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
@ -26,7 +26,7 @@ Although we got most of our images in a 2D format they do come from a 3D world.
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv

View File

@ -18,7 +18,7 @@ Theory
.. note::
The explanation below belongs to the book `Computer Vision: Algorithms and Applications <http://szeliski.org/Book/>`_ by Richard Szeliski
The explanation below belongs to the book `Computer Vision: Algorithms and Applications <http://szeliski.org/Book/>`_ by Richard Szeliski
From our previous tutorial, we know already a bit of *Pixel operators*. An interesting dyadic (two-input) operator is the *linear blend operator*:
@ -43,7 +43,7 @@ As usual, after the not-so-lengthy explanation, let's go to the code:
int main( int argc, char** argv )
{
double alpha = 0.5; double beta; double input;
double alpha = 0.5; double beta; double input;
Mat src1, src2, dst;
@ -69,7 +69,7 @@ As usual, after the not-so-lengthy explanation, let's go to the code:
beta = ( 1.0 - alpha );
addWeighted( src1, alpha, src2, beta, 0.0, dst);
imshow( "Linear Blend", dst );
waitKey(0);
@ -99,10 +99,10 @@ Explanation
#. Now we need to generate the :math:`g(x)` image. For this, the function :add_weighted:`addWeighted <>` comes quite handy:
.. code-block:: cpp
beta = ( 1.0 - alpha );
addWeighted( src1, alpha, src2, beta, 0.0, dst);
since :add_weighted:`addWeighted <>` produces:
.. math::
@ -110,12 +110,12 @@ Explanation
dst = \alpha \cdot src1 + \beta \cdot src2 + \gamma
In this case, :math:`\gamma` is the argument :math:`0.0` in the code above.
#. Create windows, show the images and wait for the user to end the program.
#. Create windows, show the images and wait for the user to end the program.
Result
=======
.. image:: images/Adding_Images_Tutorial_Result_0.jpg
:alt: Blending Images Tutorial - Final Result
:align: center
:align: center

View File

@ -99,11 +99,11 @@ Explanation
/// 2.b. Creating rectangles
rectangle( rook_image,
Point( 0, 7*w/8.0 ),
Point( w, w),
Scalar( 0, 255, 255 ),
-1,
8 );
Point( 0, 7*w/8.0 ),
Point( w, w),
Scalar( 0, 255, 255 ),
-1,
8 );
/// 2.c. Create a few lines
MyLine( rook_image, Point( 0, 15*w/16 ), Point( w, 15*w/16 ) );
@ -118,16 +118,16 @@ Explanation
.. code-block:: cpp
void MyLine( Mat img, Point start, Point end )
{
int thickness = 2;
int lineType = 8;
line( img,
start,
end,
Scalar( 0, 0, 0 ),
thickness,
lineType );
}
{
int thickness = 2;
int lineType = 8;
line( img,
start,
end,
Scalar( 0, 0, 0 ),
thickness,
lineType );
}
As we can see, *MyLine* just call the function :line:`line <>`, which does the following:
@ -145,18 +145,18 @@ Explanation
void MyEllipse( Mat img, double angle )
{
int thickness = 2;
int lineType = 8;
int thickness = 2;
int lineType = 8;
ellipse( img,
Point( w/2.0, w/2.0 ),
Size( w/4.0, w/16.0 ),
angle,
0,
360,
Scalar( 255, 0, 0 ),
thickness,
lineType );
ellipse( img,
Point( w/2.0, w/2.0 ),
Size( w/4.0, w/16.0 ),
angle,
0,
360,
Scalar( 255, 0, 0 ),
thickness,
lineType );
}
From the code above, we can observe that the function :ellipse:`ellipse <>` draws an ellipse such that:
@ -176,17 +176,17 @@ Explanation
.. code-block:: cpp
void MyFilledCircle( Mat img, Point center )
{
int thickness = -1;
int lineType = 8;
{
int thickness = -1;
int lineType = 8;
circle( img,
center,
w/32.0,
Scalar( 0, 0, 255 ),
thickness,
lineType );
}
circle( img,
center,
w/32.0,
Scalar( 0, 0, 255 ),
thickness,
lineType );
}
Similar to the ellipse function, we can observe that *circle* receives as arguments:
@ -203,41 +203,41 @@ Explanation
.. code-block:: cpp
void MyPolygon( Mat img )
{
int lineType = 8;
{
int lineType = 8;
/** Create some points */
Point rook_points[1][20];
rook_points[0][0] = Point( w/4.0, 7*w/8.0 );
rook_points[0][1] = Point( 3*w/4.0, 7*w/8.0 );
rook_points[0][2] = Point( 3*w/4.0, 13*w/16.0 );
rook_points[0][3] = Point( 11*w/16.0, 13*w/16.0 );
rook_points[0][4] = Point( 19*w/32.0, 3*w/8.0 );
rook_points[0][5] = Point( 3*w/4.0, 3*w/8.0 );
rook_points[0][6] = Point( 3*w/4.0, w/8.0 );
rook_points[0][7] = Point( 26*w/40.0, w/8.0 );
rook_points[0][8] = Point( 26*w/40.0, w/4.0 );
rook_points[0][9] = Point( 22*w/40.0, w/4.0 );
rook_points[0][10] = Point( 22*w/40.0, w/8.0 );
rook_points[0][11] = Point( 18*w/40.0, w/8.0 );
rook_points[0][12] = Point( 18*w/40.0, w/4.0 );
rook_points[0][13] = Point( 14*w/40.0, w/4.0 );
rook_points[0][14] = Point( 14*w/40.0, w/8.0 );
rook_points[0][15] = Point( w/4.0, w/8.0 );
rook_points[0][16] = Point( w/4.0, 3*w/8.0 );
rook_points[0][17] = Point( 13*w/32.0, 3*w/8.0 );
rook_points[0][18] = Point( 5*w/16.0, 13*w/16.0 );
rook_points[0][19] = Point( w/4.0, 13*w/16.0) ;
/** Create some points */
Point rook_points[1][20];
rook_points[0][0] = Point( w/4.0, 7*w/8.0 );
rook_points[0][1] = Point( 3*w/4.0, 7*w/8.0 );
rook_points[0][2] = Point( 3*w/4.0, 13*w/16.0 );
rook_points[0][3] = Point( 11*w/16.0, 13*w/16.0 );
rook_points[0][4] = Point( 19*w/32.0, 3*w/8.0 );
rook_points[0][5] = Point( 3*w/4.0, 3*w/8.0 );
rook_points[0][6] = Point( 3*w/4.0, w/8.0 );
rook_points[0][7] = Point( 26*w/40.0, w/8.0 );
rook_points[0][8] = Point( 26*w/40.0, w/4.0 );
rook_points[0][9] = Point( 22*w/40.0, w/4.0 );
rook_points[0][10] = Point( 22*w/40.0, w/8.0 );
rook_points[0][11] = Point( 18*w/40.0, w/8.0 );
rook_points[0][12] = Point( 18*w/40.0, w/4.0 );
rook_points[0][13] = Point( 14*w/40.0, w/4.0 );
rook_points[0][14] = Point( 14*w/40.0, w/8.0 );
rook_points[0][15] = Point( w/4.0, w/8.0 );
rook_points[0][16] = Point( w/4.0, 3*w/8.0 );
rook_points[0][17] = Point( 13*w/32.0, 3*w/8.0 );
rook_points[0][18] = Point( 5*w/16.0, 13*w/16.0 );
rook_points[0][19] = Point( w/4.0, 13*w/16.0) ;
const Point* ppt[1] = { rook_points[0] };
int npt[] = { 20 };
const Point* ppt[1] = { rook_points[0] };
int npt[] = { 20 };
fillPoly( img,
ppt,
npt,
1,
Scalar( 255, 255, 255 ),
lineType );
fillPoly( img,
ppt,
npt,
1,
Scalar( 255, 255, 255 ),
lineType );
}
To draw a filled polygon we use the function :fill_poly:`fillPoly <>`. We note that:
@ -255,11 +255,11 @@ Explanation
.. code-block:: cpp
rectangle( rook_image,
Point( 0, 7*w/8.0 ),
Point( w, w),
Scalar( 0, 255, 255 ),
-1,
8 );
Point( 0, 7*w/8.0 ),
Point( w, w),
Scalar( 0, 255, 255 ),
-1,
8 );
Finally we have the :rectangle:`rectangle <>` function (we did not create a special function for this guy). We note that:

View File

@ -10,7 +10,7 @@ In this tutorial you will learn how to:
.. container:: enumeratevisibleitemswithsquare
+ Access pixel values
+ Access pixel values
+ Initialize a matrix with zeros
@ -20,16 +20,16 @@ In this tutorial you will learn how to:
Theory
=======
.. note::
The explanation below belongs to the book `Computer Vision: Algorithms and Applications <http://szeliski.org/Book/>`_ by Richard Szeliski
The explanation below belongs to the book `Computer Vision: Algorithms and Applications <http://szeliski.org/Book/>`_ by Richard Szeliski
Image Processing
--------------------
.. container:: enumeratevisibleitemswithsquare
* A general image processing operator is a function that takes one or more input images and produces an output image.
* A general image processing operator is a function that takes one or more input images and produces an output image.
* Image transforms can be seen as:
@ -54,18 +54,18 @@ Brightness and contrast adjustments
* Two commonly used point processes are *multiplication* and *addition* with a constant:
.. math::
g(x) = \alpha f(x) + \beta
* The parameters :math:`\alpha > 0` and :math:`\beta` are often called the *gain* and *bias* parameters; sometimes these parameters are said to control *contrast* and *brightness* respectively.
* You can think of :math:`f(x)` as the source image pixels and :math:`g(x)` as the output image pixels. Then, more conveniently we can write the expression as:
.. math::
g(i,j) = \alpha \cdot f(i,j) + \beta
where :math:`i` and :math:`j` indicates that the pixel is located in the *i-th* row and *j-th* column.
where :math:`i` and :math:`j` indicates that the pixel is located in the *i-th* row and *j-th* column.
Code
=====
@ -91,7 +91,7 @@ Code
Mat image = imread( argv[1] );
Mat new_image = Mat::zeros( image.size(), image.type() );
/// Initialize values
/// Initialize values
std::cout<<" Basic Linear Transforms "<<std::endl;
std::cout<<"-------------------------"<<std::endl;
std::cout<<"* Enter the alpha value [1.0-3.0]: ";std::cin>>alpha;
@ -102,7 +102,7 @@ Code
{ for( int x = 0; x < image.cols; x++ )
{ for( int c = 0; c < 3; c++ )
{
new_image.at<Vec3b>(y,x)[c] =
new_image.at<Vec3b>(y,x)[c] =
saturate_cast<uchar>( alpha*( image.at<Vec3b>(y,x)[c] ) + beta );
}
}
@ -133,41 +133,41 @@ Explanation
#. We load an image using :imread:`imread <>` and save it in a Mat object:
.. code-block:: cpp
Mat image = imread( argv[1] );
#. Now, since we will make some transformations to this image, we need a new Mat object to store it. Also, we want this to have the following features:
.. container:: enumeratevisibleitemswithsquare
* Initial pixel values equal to zero
* Same size and type as the original image
.. code-block:: cpp
Mat new_image = Mat::zeros( image.size(), image.type() );
We observe that :mat_zeros:`Mat::zeros <>` returns a Matlab-style zero initializer based on *image.size()* and *image.type()*
Mat new_image = Mat::zeros( image.size(), image.type() );
We observe that :mat_zeros:`Mat::zeros <>` returns a Matlab-style zero initializer based on *image.size()* and *image.type()*
#. Now, to perform the operation :math:`g(i,j) = \alpha \cdot f(i,j) + \beta` we will access to each pixel in image. Since we are operating with RGB images, we will have three values per pixel (R, G and B), so we will also access them separately. Here is the piece of code:
.. code-block:: cpp
for( int y = 0; y < image.rows; y++ )
{ for( int x = 0; x < image.cols; x++ )
{ for( int c = 0; c < 3; c++ )
{ new_image.at<Vec3b>(y,x)[c] =
{ new_image.at<Vec3b>(y,x)[c] =
saturate_cast<uchar>( alpha*( image.at<Vec3b>(y,x)[c] ) + beta ); }
}
}
Notice the following:
.. container:: enumeratevisibleitemswithsquare
* To access each pixel in the images we are using this syntax: *image.at<Vec3b>(y,x)[c]* where *y* is the row, *x* is the column and *c* is R, G or B (0, 1 or 2).
* To access each pixel in the images we are using this syntax: *image.at<Vec3b>(y,x)[c]* where *y* is the row, *x* is the column and *c* is R, G or B (0, 1 or 2).
* Since the operation :math:`\alpha \cdot p(i,j) + \beta` can give values out of range or not integers (if :math:`\alpha` is float), we use :saturate_cast:`saturate_cast <>` to make sure the values are valid.
@ -175,7 +175,7 @@ Explanation
#. Finally, we create windows and show the images, the usual way.
.. code-block:: cpp
namedWindow("Original Image", 1);
namedWindow("New Image", 1);
@ -185,9 +185,9 @@ Explanation
waitKey(0);
.. note::
Instead of using the **for** loops to access each pixel, we could have simply used this command:
.. code-block:: cpp
image.convertTo(new_image, -1, alpha, beta);
@ -211,4 +211,4 @@ Result
.. image:: images/Basic_Linear_Transform_Tutorial_Result_0.jpg
:alt: Basic Linear Transform - Final Result
:align: center
:align: center

View File

@ -4,22 +4,22 @@ Discrete Fourier Transform
**************************
Goal
====
====
We'll seek answers for the following questions:
We'll seek answers for the following questions:
.. container:: enumeratevisibleitemswithsquare
+ What is a Fourier transform and why use it?
+ How to do it in OpenCV?
+ What is a Fourier transform and why use it?
+ How to do it in OpenCV?
+ Usage of functions such as: :imgprocfilter:`copyMakeBorder() <copymakeborder>`, :operationsonarrays:`merge() <merge>`, :operationsonarrays:`dft() <dft>`, :operationsonarrays:`getOptimalDFTSize() <getoptimaldftsize>`, :operationsonarrays:`log() <log>` and :operationsonarrays:`normalize() <normalize>` .
Source code
===========
You can :download:`download this from here <../../../../samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp>` or find it in the :file:`samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp` of the OpenCV source code library.
You can :download:`download this from here <../../../../samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp>` or find it in the :file:`samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp` of the OpenCV source code library.
Here's a sample usage of :operationsonarrays:`dft() <dft>` :
Here's a sample usage of :operationsonarrays:`dft() <dft>` :
.. literalinclude:: ../../../../samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp
:language: cpp
@ -30,11 +30,11 @@ Here's a sample usage of :operationsonarrays:`dft() <dft>` :
Explanation
===========
The Fourier Transform will decompose an image into its sinus and cosines components. In other words, it will transform an image from its spatial domain to its frequency domain. The idea is that any function may be approximated exactly with the sum of infinite sinus and cosines functions. The Fourier Transform is a way how to do this. Mathematically a two dimensional images Fourier transform is:
The Fourier Transform will decompose an image into its sinus and cosines components. In other words, it will transform an image from its spatial domain to its frequency domain. The idea is that any function may be approximated exactly with the sum of infinite sinus and cosines functions. The Fourier Transform is a way how to do this. Mathematically a two dimensional images Fourier transform is:
.. math::
F(k,l) = \displaystyle\sum\limits_{i=0}^{N-1}\sum\limits_{j=0}^{N-1} f(i,j)e^{-i2\pi(\frac{ki}{N}+\frac{lj}{N})}
F(k,l) = \displaystyle\sum\limits_{i=0}^{N-1}\sum\limits_{j=0}^{N-1} f(i,j)e^{-i2\pi(\frac{ki}{N}+\frac{lj}{N})}
e^{ix} = \cos{x} + i\sin {x}
@ -44,65 +44,65 @@ In this sample I'll show how to calculate and show the *magnitude* image of a Fo
1. **Expand the image to an optimal size**. The performance of a DFT is dependent of the image size. It tends to be the fastest for image sizes that are multiple of the numbers two, three and five. Therefore, to achieve maximal performance it is generally a good idea to pad border values to the image to get a size with such traits. The :operationsonarrays:`getOptimalDFTSize() <getoptimaldftsize>` returns this optimal size and we can use the :imgprocfilter:`copyMakeBorder() <copymakeborder>` function to expand the borders of an image:
.. code-block:: cpp
.. code-block:: cpp
Mat padded; //expand input image to optimal size
int m = getOptimalDFTSize( I.rows );
int n = getOptimalDFTSize( I.cols ); // on the border add zero pixels
copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0));
The appended pixels are initialized with zero.
The appended pixels are initialized with zero.
2. **Make place for both the complex and the real values**. The result of a Fourier Transform is complex. This implies that for each image value the result is two image values (one per component). Moreover, the frequency domains range is much larger than its spatial counterpart. Therefore, we store these usually at least in a *float* format. Therefore we'll convert our input image to this type and expand it with another channel to hold the complex values:
.. code-block:: cpp
.. code-block:: cpp
Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
Mat complexI;
merge(planes, 2, complexI); // Add to the expanded another plane with zeros
3. **Make the Discrete Fourier Transform**. It's possible an in-place calculation (same input as output):
3. **Make the Discrete Fourier Transform**. It's possible an in-place calculation (same input as output):
.. code-block:: cpp
.. code-block:: cpp
dft(complexI, complexI); // this way the result may fit in the source matrix
4. **Transform the real and complex values to magnitude**. A complex number has a real (*Re*) and a complex (imaginary - *Im*) part. The results of a DFT are complex numbers. The magnitude of a DFT is:
4. **Transform the real and complex values to magnitude**. A complex number has a real (*Re*) and a complex (imaginary - *Im*) part. The results of a DFT are complex numbers. The magnitude of a DFT is:
.. math::
M = \sqrt[2]{ {Re(DFT(I))}^2 + {Im(DFT(I))}^2}
Translated to OpenCV code:
Translated to OpenCV code:
.. code-block:: cpp
.. code-block:: cpp
split(complexI, planes); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))
magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude
magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude
Mat magI = planes[0];
5. **Switch to a logarithmic scale**. It turns out that the dynamic range of the Fourier coefficients is too large to be displayed on the screen. We have some small and some high changing values that we can't observe like this. Therefore the high values will all turn out as white points, while the small ones as black. To use the gray scale values to for visualization we can transform our linear scale to a logarithmic one:
5. **Switch to a logarithmic scale**. It turns out that the dynamic range of the Fourier coefficients is too large to be displayed on the screen. We have some small and some high changing values that we can't observe like this. Therefore the high values will all turn out as white points, while the small ones as black. To use the gray scale values to for visualization we can transform our linear scale to a logarithmic one:
.. math::
M_1 = \log{(1 + M)}
Translated to OpenCV code:
Translated to OpenCV code:
.. code-block:: cpp
.. code-block:: cpp
magI += Scalar::all(1); // switch to logarithmic scale
log(magI, magI);
6. **Crop and rearrange**. Remember, that at the first step, we expanded the image? Well, it's time to throw away the newly introduced values. For visualization purposes we may also rearrange the quadrants of the result, so that the origin (zero, zero) corresponds with the image center.
6. **Crop and rearrange**. Remember, that at the first step, we expanded the image? Well, it's time to throw away the newly introduced values. For visualization purposes we may also rearrange the quadrants of the result, so that the origin (zero, zero) corresponds with the image center.
.. code-block:: cpp
.. code-block:: cpp
magI = magI(Rect(0, 0, magI.cols & -2, magI.rows & -2));
int cx = magI.cols/2;
int cy = magI.rows/2;
Mat q0(magI, Rect(0, 0, cx, cy)); // Top-Left - Create a ROI per quadrant
Mat q0(magI, Rect(0, 0, cx, cy)); // Top-Left - Create a ROI per quadrant
Mat q1(magI, Rect(cx, 0, cx, cy)); // Top-Right
Mat q2(magI, Rect(0, cy, cx, cy)); // Bottom-Left
Mat q3(magI, Rect(cx, cy, cx, cy)); // Bottom-Right
@ -116,25 +116,25 @@ In this sample I'll show how to calculate and show the *magnitude* image of a Fo
q2.copyTo(q1);
tmp.copyTo(q2);
7. **Normalize**. This is done again for visualization purposes. We now have the magnitudes, however this are still out of our image display range of zero to one. We normalize our values to this range using the :operationsonarrays:`normalize() <normalize>` function.
7. **Normalize**. This is done again for visualization purposes. We now have the magnitudes, however this are still out of our image display range of zero to one. We normalize our values to this range using the :operationsonarrays:`normalize() <normalize>` function.
.. code-block:: cpp
.. code-block:: cpp
normalize(magI, magI, 0, 1, CV_MINMAX); // Transform the matrix with float values into a
normalize(magI, magI, 0, 1, CV_MINMAX); // Transform the matrix with float values into a
// viewable image form (float between values 0 and 1).
Result
======
An application idea would be to determine the geometrical orientation present in the image. For example, let us find out if a text is horizontal or not? Looking at some text you'll notice that the text lines sort of form also horizontal lines and the letters form sort of vertical lines. These two main components of a text snippet may be also seen in case of the Fourier transform. Let us use :download:`this horizontal <../../../../samples/cpp/tutorial_code/images/imageTextN.png>` and :download:`this rotated<../../../../samples/cpp/tutorial_code/images/imageTextR.png>` image about a text.
An application idea would be to determine the geometrical orientation present in the image. For example, let us find out if a text is horizontal or not? Looking at some text you'll notice that the text lines sort of form also horizontal lines and the letters form sort of vertical lines. These two main components of a text snippet may be also seen in case of the Fourier transform. Let us use :download:`this horizontal <../../../../samples/cpp/tutorial_code/images/imageTextN.png>` and :download:`this rotated<../../../../samples/cpp/tutorial_code/images/imageTextR.png>` image about a text.
In case of the horizontal text:
In case of the horizontal text:
.. image:: images/result_normal.jpg
:alt: In case of normal text
:align: center
In case of a rotated text:
In case of a rotated text:
.. image:: images/result_rotated.jpg
:alt: In case of rotated text

View File

@ -4,9 +4,9 @@ File Input and Output using XML and YAML files
**********************************************
Goal
====
====
You'll find answers for the following questions:
You'll find answers for the following questions:
.. container:: enumeratevisibleitemswithsquare
@ -18,7 +18,7 @@ You'll find answers for the following questions:
Source code
===========
You can :download:`download this from here <../../../../samples/cpp/tutorial_code/core/file_input_output/file_input_output.cpp>` or find it in the :file:`samples/cpp/tutorial_code/core/file_input_output/file_input_output.cpp` of the OpenCV source code library.
You can :download:`download this from here <../../../../samples/cpp/tutorial_code/core/file_input_output/file_input_output.cpp>` or find it in the :file:`samples/cpp/tutorial_code/core/file_input_output/file_input_output.cpp` of the OpenCV source code library.
Here's a sample code of how to achieve all the stuff enumerated at the goal list.
@ -31,9 +31,9 @@ Here's a sample code of how to achieve all the stuff enumerated at the goal list
Explanation
===========
Here we talk only about XML and YAML file inputs. Your output (and its respective input) file may have only one of these extensions and the structure coming from this. They are two kinds of data structures you may serialize: *mappings* (like the STL map) and *element sequence* (like the STL vector>. The difference between these is that in a map every element has a unique name through what you may access it. For sequences you need to go through them to query a specific item.
Here we talk only about XML and YAML file inputs. Your output (and its respective input) file may have only one of these extensions and the structure coming from this. They are two kinds of data structures you may serialize: *mappings* (like the STL map) and *element sequence* (like the STL vector>. The difference between these is that in a map every element has a unique name through what you may access it. For sequences you need to go through them to query a specific item.
1. **XML\\YAML File Open and Close.** Before you write any content to such file you need to open it and at the end to close it. The XML\YAML data structure in OpenCV is :xmlymlpers:`FileStorage <filestorage>`. To specify that this structure to which file binds on your hard drive you can use either its constructor or the *open()* function of this:
1. **XML\\YAML File Open and Close.** Before you write any content to such file you need to open it and at the end to close it. The XML\YAML data structure in OpenCV is :xmlymlpers:`FileStorage <filestorage>`. To specify that this structure to which file binds on your hard drive you can use either its constructor or the *open()* function of this:
.. code-block:: cpp
@ -42,29 +42,29 @@ Here we talk only about XML and YAML file inputs. Your output (and its respectiv
\\...
fs.open(filename, FileStorage::READ);
Either one of this you use the second argument is a constant specifying the type of operations you'll be able to on them: WRITE, READ or APPEND. The extension specified in the file name also determinates the output format that will be used. The output may be even compressed if you specify an extension such as *.xml.gz*.
Either one of this you use the second argument is a constant specifying the type of operations you'll be able to on them: WRITE, READ or APPEND. The extension specified in the file name also determinates the output format that will be used. The output may be even compressed if you specify an extension such as *.xml.gz*.
The file automatically closes when the :xmlymlpers:`FileStorage <filestorage>` objects is destroyed. However, you may explicitly call for this by using the *release* function:
The file automatically closes when the :xmlymlpers:`FileStorage <filestorage>` objects is destroyed. However, you may explicitly call for this by using the *release* function:
.. code-block:: cpp
fs.release(); // explicit close
#. **Input and Output of text and numbers.** The data structure uses the same << output operator that the STL library. For outputting any type of data structure we need first to specify its name. We do this by just simply printing out the name of this. For basic types you may follow this with the print of the value :
#. **Input and Output of text and numbers.** The data structure uses the same << output operator that the STL library. For outputting any type of data structure we need first to specify its name. We do this by just simply printing out the name of this. For basic types you may follow this with the print of the value :
.. code-block:: cpp
fs << "iterationNr" << 100;
Reading in is a simple addressing (via the [] operator) and casting operation or a read via the >> operator :
Reading in is a simple addressing (via the [] operator) and casting operation or a read via the >> operator :
.. code-block:: cpp
int itNr;
int itNr;
fs["iterationNr"] >> itNr;
itNr = (int) fs["iterationNr"];
#. **Input\\Output of OpenCV Data structures.** Well these behave exactly just as the basic C++ types:
#. **Input\\Output of OpenCV Data structures.** Well these behave exactly just as the basic C++ types:
.. code-block:: cpp
@ -77,7 +77,7 @@ Here we talk only about XML and YAML file inputs. Your output (and its respectiv
fs["R"] >> R; // Read cv::Mat
fs["T"] >> T;
#. **Input\\Output of vectors (arrays) and associative maps.** As I mentioned beforehand we can output maps and sequences (array, vector) too. Again we first print the name of the variable and then we have to specify if our output is either a sequence or map.
#. **Input\\Output of vectors (arrays) and associative maps.** As I mentioned beforehand we can output maps and sequences (array, vector) too. Again we first print the name of the variable and then we have to specify if our output is either a sequence or map.
For sequence before the first element print the "[" character and after the last one the "]" character:
@ -95,7 +95,7 @@ Here we talk only about XML and YAML file inputs. Your output (and its respectiv
fs << "{" << "One" << 1;
fs << "Two" << 2 << "}";
To read from these we use the :xmlymlpers:`FileNode <filenode>` and the :xmlymlpers:`FileNodeIterator <filenodeiterator>` data structures. The [] operator of the :xmlymlpers:`FileStorage <filestorage>` class returns a :xmlymlpers:`FileNode <filenode>` data type. If the node is sequential we can use the :xmlymlpers:`FileNodeIterator <filenodeiterator>` to iterate through the items:
To read from these we use the :xmlymlpers:`FileNode <filenode>` and the :xmlymlpers:`FileNodeIterator <filenodeiterator>` data structures. The [] operator of the :xmlymlpers:`FileStorage <filestorage>` class returns a :xmlymlpers:`FileNode <filenode>` data type. If the node is sequential we can use the :xmlymlpers:`FileNodeIterator <filenodeiterator>` to iterate through the items:
.. code-block:: cpp
@ -115,8 +115,8 @@ Here we talk only about XML and YAML file inputs. Your output (and its respectiv
.. code-block:: cpp
n = fs["Mapping"]; // Read mappings from a sequence
cout << "Two " << (int)(n["Two"]) << "; ";
cout << "One " << (int)(n["One"]) << endl << endl;
cout << "Two " << (int)(n["Two"]) << "; ";
cout << "One " << (int)(n["One"]) << endl << endl;
#. **Read and write your own data structures.** Suppose you have a data structure such as:
@ -148,7 +148,7 @@ Here we talk only about XML and YAML file inputs. Your output (and its respectiv
id = (string)node["id"];
}
Then you need to add the following functions definitions outside the class:
Then you need to add the following functions definitions outside the class:
.. code-block:: cpp
@ -175,17 +175,17 @@ Here we talk only about XML and YAML file inputs. Your output (and its respectiv
fs << "MyData" << m; // your own data structures
fs["MyData"] >> m; // Read your own structure_
Or to try out reading a non-existing read:
Or to try out reading a non-existing read:
.. code-block:: cpp
fs["NonExisting"] >> m; // Do not add a fs << "NonExisting" << m command for this to work
fs["NonExisting"] >> m; // Do not add a fs << "NonExisting" << m command for this to work
cout << endl << "NonExisting = " << endl << m << endl;
Result
======
Well mostly we just print out the defined numbers. On the screen of your console you could see:
Well mostly we just print out the defined numbers. On the screen of your console you could see:
.. code-block:: bash
@ -212,7 +212,7 @@ Well mostly we just print out the defined numbers. On the screen of your console
Tip: Open up output.xml with a text editor to see the serialized data.
Nevertheless, it's much more interesting what you may see in the output xml file:
Nevertheless, it's much more interesting what you may see in the output xml file:
.. code-block:: xml
@ -242,7 +242,7 @@ Nevertheless, it's much more interesting what you may see in the output xml file
<id>mydata1234</id></MyData>
</opencv_storage>
Or the YAML file:
Or the YAML file:
.. code-block:: yaml
@ -277,4 +277,3 @@ You may observe a runtime instance of this on the `YouTube here <https://www.you
<div align="center">
<iframe title="File Input and Output using XML and YAML files in OpenCV" width="560" height="349" src="http://www.youtube.com/embed/A4yqVnByMMM?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>
</div>

View File

@ -4,9 +4,9 @@ How to scan images, lookup tables and time measurement with OpenCV
*******************************************************************
Goal
====
====
We'll seek answers for the following questions:
We'll seek answers for the following questions:
.. container:: enumeratevisibleitemswithsquare
@ -18,11 +18,11 @@ We'll seek answers for the following questions:
Our test case
=============
Let us consider a simple color reduction method. Using the unsigned char C and C++ type for matrix item storing a channel of pixel may have up to 256 different values. For a three channel image this can allow the formation of way too many colors (16 million to be exact). Working with so many color shades may give a heavy blow to our algorithm performance. However, sometimes it is enough to work with a lot less of them to get the same final result.
Let us consider a simple color reduction method. Using the unsigned char C and C++ type for matrix item storing a channel of pixel may have up to 256 different values. For a three channel image this can allow the formation of way too many colors (16 million to be exact). Working with so many color shades may give a heavy blow to our algorithm performance. However, sometimes it is enough to work with a lot less of them to get the same final result.
In this cases it's common that we make a *color space reduction*. This means that we divide the color space current value with a new input value to end up with fewer colors. For instance every value between zero and nine takes the new value zero, every value between ten and nineteen the value ten and so on.
In this cases it's common that we make a *color space reduction*. This means that we divide the color space current value with a new input value to end up with fewer colors. For instance every value between zero and nine takes the new value zero, every value between ten and nineteen the value ten and so on.
When you divide an *uchar* (unsigned char - aka values between zero and 255) value with an *int* value the result will be also *char*. These values may only be char values. Therefore, any fraction will be rounded down. Taking advantage of this fact the upper operation in the *uchar* domain may be expressed as:
When you divide an *uchar* (unsigned char - aka values between zero and 255) value with an *int* value the result will be also *char*. These values may only be char values. Therefore, any fraction will be rounded down. Taking advantage of this fact the upper operation in the *uchar* domain may be expressed as:
.. math::
@ -30,11 +30,11 @@ When you divide an *uchar* (unsigned char - aka values between zero and 255) val
A simple color space reduction algorithm would consist of just passing through every pixel of an image matrix and applying this formula. It's worth noting that we do a divide and a multiplication operation. These operations are bloody expensive for a system. If possible it's worth avoiding them by using cheaper operations such as a few subtractions, addition or in best case a simple assignment. Furthermore, note that we only have a limited number of input values for the upper operation. In case of the *uchar* system this is 256 to be exact.
Therefore, for larger images it would be wise to calculate all possible values beforehand and during the assignment just make the assignment, by using a lookup table. Lookup tables are simple arrays (having one or more dimensions) that for a given input value variation holds the final output value. Its strength lies that we do not need to make the calculation, we just need to read the result.
Therefore, for larger images it would be wise to calculate all possible values beforehand and during the assignment just make the assignment, by using a lookup table. Lookup tables are simple arrays (having one or more dimensions) that for a given input value variation holds the final output value. Its strength lies that we do not need to make the calculation, we just need to read the result.
Our test case program (and the sample presented here) will do the following: read in a console line argument image (that may be either color or gray scale - console line argument too) and apply the reduction with the given console line argument integer value. In OpenCV, at the moment they are three major ways of going through an image pixel by pixel. To make things a little more interesting will make the scanning for each image using all of these methods, and print out how long it took.
Our test case program (and the sample presented here) will do the following: read in a console line argument image (that may be either color or gray scale - console line argument too) and apply the reduction with the given console line argument integer value. In OpenCV, at the moment they are three major ways of going through an image pixel by pixel. To make things a little more interesting will make the scanning for each image using all of these methods, and print out how long it took.
You can download the full source code :download:`here <../../../../samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp>` or look it up in the samples directory of OpenCV at the cpp tutorial code for the core section. Its basic usage is:
You can download the full source code :download:`here <../../../../samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp>` or look it up in the samples directory of OpenCV at the cpp tutorial code for the core section. Its basic usage is:
.. code-block:: bash
@ -45,25 +45,25 @@ The final argument is optional. If given the image will be loaded in gray scale
.. literalinclude:: ../../../../samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp
:language: cpp
:tab-width: 4
:lines: 48-60
:lines: 48-60
Here we first use the C++ *stringstream* class to convert the third command line argument from text to an integer format. Then we use a simple look and the upper formula to calculate the lookup table. No OpenCV specific stuff here.
Another issue is how do we measure time? Well OpenCV offers two simple functions to achieve this :UtilitySystemFunctions:`getTickCount() <gettickcount>` and :UtilitySystemFunctions:`getTickFrequency() <gettickfrequency>`. The first returns the number of ticks of your systems CPU from a certain event (like since you booted your system). The second returns how many times your CPU emits a tick during a second. So to measure in seconds the number of time elapsed between two operations is easy as:
Another issue is how do we measure time? Well OpenCV offers two simple functions to achieve this :UtilitySystemFunctions:`getTickCount() <gettickcount>` and :UtilitySystemFunctions:`getTickFrequency() <gettickfrequency>`. The first returns the number of ticks of your systems CPU from a certain event (like since you booted your system). The second returns how many times your CPU emits a tick during a second. So to measure in seconds the number of time elapsed between two operations is easy as:
.. code-block:: cpp
double t = (double)getTickCount();
// do something ...
t = ((double)getTickCount() - t)/getTickFrequency();
t = ((double)getTickCount() - t)/getTickFrequency();
cout << "Times passed in seconds: " << t << endl;
.. _How_Image_Stored_Memory:
.. _How_Image_Stored_Memory:
How the image matrix is stored in the memory?
=============================================
As you could already read in my :ref:`matTheBasicImageContainer` tutorial the size of the matrix depends of the color system used. More accurately, it depends from the number of channels used. In case of a gray scale image we have something like:
As you could already read in my :ref:`matTheBasicImageContainer` tutorial the size of the matrix depends of the color system used. More accurately, it depends from the number of channels used. In case of a gray scale image we have something like:
.. math::
@ -94,14 +94,14 @@ Note that the order of the channels is inverse: BGR instead of RGB. Because in m
The efficient way
=================
When it comes to performance you cannot beat the classic C style operator[] (pointer) access. Therefore, the most efficient method we can recommend for making the assignment is:
When it comes to performance you cannot beat the classic C style operator[] (pointer) access. Therefore, the most efficient method we can recommend for making the assignment is:
.. literalinclude:: ../../../../samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp
:language: cpp
:tab-width: 4
:lines: 125-152
Here we basically just acquire a pointer to the start of each row and go through it until it ends. In the special case that the matrix is stored in a continues manner we only need to request the pointer a single time and go all the way to the end. We need to look out for color images: we have three channels so we need to pass through three times more items in each row.
Here we basically just acquire a pointer to the start of each row and go through it until it ends. In the special case that the matrix is stored in a continues manner we only need to request the pointer a single time and go all the way to the end. We need to look out for color images: we have three channels so we need to pass through three times more items in each row.
There's another way of this. The *data* data member of a *Mat* object returns the pointer to the first row, first column. If this pointer is null you have no valid input in that object. Checking this is the simplest method to check if your image loading was a success. In case the storage is continues we can use this to go through the whole data pointer. In case of a gray scale image this would look like:
@ -114,17 +114,17 @@ There's another way of this. The *data* data member of a *Mat* object returns th
You would get the same result. However, this code is a lot harder to read later on. It gets even harder if you have some more advanced technique there. Moreover, in practice I've observed you'll get the same performance result (as most of the modern compilers will probably make this small optimization trick automatically for you).
The iterator (safe) method
The iterator (safe) method
==========================
In case of the efficient way making sure that you pass through the right amount of *uchar* fields and to skip the gaps that may occur between the rows was your responsibility. The iterator method is considered a safer way as it takes over these tasks from the user. All you need to do is ask the begin and the end of the image matrix and then just increase the begin iterator until you reach the end. To acquire the value *pointed* by the iterator use the * operator (add it before it).
In case of the efficient way making sure that you pass through the right amount of *uchar* fields and to skip the gaps that may occur between the rows was your responsibility. The iterator method is considered a safer way as it takes over these tasks from the user. All you need to do is ask the begin and the end of the image matrix and then just increase the begin iterator until you reach the end. To acquire the value *pointed* by the iterator use the * operator (add it before it).
.. literalinclude:: ../../../../samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp
:language: cpp
:tab-width: 4
:lines: 154-182
In case of color images we have three uchar items per column. This may be considered a short vector of uchar items, that has been baptized in OpenCV with the *Vec3b* name. To access the n-th sub column we use simple operator[] access. It's important to remember that OpenCV iterators go through the columns and automatically skip to the next row. Therefore in case of color images if you use a simple *uchar* iterator you'll be able to access only the blue channel values.
In case of color images we have three uchar items per column. This may be considered a short vector of uchar items, that has been baptized in OpenCV with the *Vec3b* name. To access the n-th sub column we use simple operator[] access. It's important to remember that OpenCV iterators go through the columns and automatically skip to the next row. Therefore in case of color images if you use a simple *uchar* iterator you'll be able to access only the blue channel values.
On-the-fly address calculation with reference returning
=======================================================
@ -136,7 +136,7 @@ The final method isn't recommended for scanning. It was made to acquire or modif
:tab-width: 4
:lines: 184-216
The functions takes your input type and coordinates and calculates on the fly the address of the queried item. Then returns a reference to that. This may be a constant when you *get* the value and non-constant when you *set* the value. As a safety step in **debug mode only*** there is performed a check that your input coordinates are valid and does exist. If this isn't the case you'll get a nice output message of this on the standard error output stream. Compared to the efficient way in release mode the only difference in using this is that for every element of the image you'll get a new row pointer for what we use the C operator[] to acquire the column element.
The functions takes your input type and coordinates and calculates on the fly the address of the queried item. Then returns a reference to that. This may be a constant when you *get* the value and non-constant when you *set* the value. As a safety step in **debug mode only*** there is performed a check that your input coordinates are valid and does exist. If this isn't the case you'll get a nice output message of this on the standard error output stream. Compared to the efficient way in release mode the only difference in using this is that for every element of the image you'll get a new row pointer for what we use the C operator[] to acquire the column element.
If you need to multiple lookups using this method for an image it may be troublesome and time consuming to enter the type and the at keyword for each of the accesses. To solve this problem OpenCV has a :basicstructures:`Mat_ <id3>` data type. It's the same as Mat with the extra need that at definition you need to specify the data type through what to look at the data matrix, however in return you can use the operator() for fast access of items. To make things even better this is easily convertible from and to the usual :basicstructures:`Mat <id3>` data type. A sample usage of this you can see in case of the color images of the upper function. Nevertheless, it's important to note that the same operation (with the same runtime speed) could have been done with the :basicstructures:`at() <mat-at>` function. It's just a less to write for the lazy programmer trick.

View File

@ -6,7 +6,7 @@ Interoperability with OpenCV 1
Goal
====
For the OpenCV developer team it's important to constantly improve the library. We are constantly thinking about methods that will ease your work process, while still maintain the libraries flexibility. The new C++ interface is a development of us that serves this goal. Nevertheless, backward compatibility remains important. We do not want to break your code written for earlier version of the OpenCV library. Therefore, we made sure that we add some functions that deal with this. In the following you'll learn:
For the OpenCV developer team it's important to constantly improve the library. We are constantly thinking about methods that will ease your work process, while still maintain the libraries flexibility. The new C++ interface is a development of us that serves this goal. Nevertheless, backward compatibility remains important. We do not want to break your code written for earlier version of the OpenCV library. Therefore, we made sure that we add some functions that deal with this. In the following you'll learn:
.. container:: enumeratevisibleitemswithsquare
@ -17,9 +17,9 @@ For the OpenCV developer team it's important to constantly improve the library.
General
=======
When making the switch you first need to learn some about the new data structure for images: :ref:`matTheBasicImageContainer`, this replaces the old *CvMat* and *IplImage* ones. Switching to the new functions is easier. You just need to remember a couple of new things.
When making the switch you first need to learn some about the new data structure for images: :ref:`matTheBasicImageContainer`, this replaces the old *CvMat* and *IplImage* ones. Switching to the new functions is easier. You just need to remember a couple of new things.
OpenCV 2 received reorganization. No longer are all the functions crammed into a single library. We have many modules, each of them containing data structures and functions relevant to certain tasks. This way you do not need to ship a large library if you use just a subset of OpenCV. This means that you should also include only those headers you will use. For example:
OpenCV 2 received reorganization. No longer are all the functions crammed into a single library. We have many modules, each of them containing data structures and functions relevant to certain tasks. This way you do not need to ship a large library if you use just a subset of OpenCV. This means that you should also include only those headers you will use. For example:
.. code-block:: cpp
@ -28,13 +28,13 @@ OpenCV 2 received reorganization. No longer are all the functions crammed into a
#include <opencv2/highgui/highgui.hpp>
All the OpenCV related stuff is put into the *cv* namespace to avoid name conflicts with other libraries data structures and functions. Therefore, either you need to prepend the *cv::* keyword before everything that comes from OpenCV or after the includes, you just add a directive to use this:
All the OpenCV related stuff is put into the *cv* namespace to avoid name conflicts with other libraries data structures and functions. Therefore, either you need to prepend the *cv::* keyword before everything that comes from OpenCV or after the includes, you just add a directive to use this:
.. code-block:: cpp
using namespace cv; // The new C++ interface API is inside this namespace. Import it.
Because the functions are already in a namespace there is no need for them to contain the *cv* prefix in their name. As such all the new C++ compatible functions don't have this and they follow the camel case naming rule. This means the first letter is small (unless it's a name, like Canny) and the subsequent words start with a capital letter (like *copyMakeBorder*).
Because the functions are already in a namespace there is no need for them to contain the *cv* prefix in their name. As such all the new C++ compatible functions don't have this and they follow the camel case naming rule. This means the first letter is small (unless it's a name, like Canny) and the subsequent words start with a capital letter (like *copyMakeBorder*).
Now, remember that you need to link to your application all the modules you use, and in case you are on Windows using the *DLL* system you will need to add, again, to the path all the binaries. For more in-depth information if you're on Windows read :ref:`Windows_Visual_Studio_How_To` and for Linux an example usage is explained in :ref:`Linux_Eclipse_Usage`.
@ -42,7 +42,7 @@ Now for converting the *Mat* object you can use either the *IplImage* or the *Cv
.. code-block:: cpp
Mat I;
Mat I;
IplImage pI = I;
CvMat mI = I;
@ -50,9 +50,9 @@ Now if you want pointers the conversion gets just a little more complicated. The
.. code-block:: cpp
Mat I;
IplImage* pI = &I.operator IplImage();
CvMat* mI = &I.operator CvMat();
Mat I;
IplImage* pI = &I.operator IplImage();
CvMat* mI = &I.operator CvMat();
One of the biggest complaints of the C interface is that it leaves all the memory management to you. You need to figure out when it is safe to release your unused objects and make sure you do so before the program finishes or you could have troublesome memory leeks. To work around this issue in OpenCV there is introduced a sort of smart pointer. This will automatically release the object when it's no longer in use. To use this declare the pointers as a specialization of the *Ptr* :
@ -60,11 +60,11 @@ One of the biggest complaints of the C interface is that it leaves all the memor
Ptr<IplImage> piI = &I.operator IplImage();
Converting from the C data structures to the *Mat* is done by passing these inside its constructor. For example:
Converting from the C data structures to the *Mat* is done by passing these inside its constructor. For example:
.. code-block:: cpp
Mat K(piL), L;
Mat K(piL), L;
L = Mat(pI);
A case study
@ -79,7 +79,7 @@ Now that you have the basics done :download:`here's <../../../../samples/cpp/tut
:tab-width: 4
:lines: 1-9, 22-25, 27-44
Here you can observe that with the new structure we have no pointer problems, although it is possible to use the old functions and in the end just transform the result to a *Mat* object.
Here you can observe that with the new structure we have no pointer problems, although it is possible to use the old functions and in the end just transform the result to a *Mat* object.
.. literalinclude:: ../../../../samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp
:language: cpp
@ -87,7 +87,7 @@ Here you can observe that with the new structure we have no pointer problems, al
:tab-width: 4
:lines: 46-51
Because, we want to mess around with the images luma component we first convert from the default RGB to the YUV color space and then split the result up into separate planes. Here the program splits: in the first example it processes each plane using one of the three major image scanning algorithms in OpenCV (C [] operator, iterator, individual element access). In a second variant we add to the image some Gaussian noise and then mix together the channels according to some formula.
Because, we want to mess around with the images luma component we first convert from the default RGB to the YUV color space and then split the result up into separate planes. Here the program splits: in the first example it processes each plane using one of the three major image scanning algorithms in OpenCV (C [] operator, iterator, individual element access). In a second variant we add to the image some Gaussian noise and then mix together the channels according to some formula.
The scanning version looks like:
@ -97,7 +97,7 @@ The scanning version looks like:
:tab-width: 4
:lines: 55-75
Here you can observe that we may go through all the pixels of an image in three fashions: an iterator, a C pointer and an individual element access style. You can read a more in-depth description of these in the :ref:`howToScanImagesOpenCV` tutorial. Converting from the old function names is easy. Just remove the cv prefix and use the new *Mat* data structure. Here's an example of this by using the weighted addition function:
Here you can observe that we may go through all the pixels of an image in three fashions: an iterator, a C pointer and an individual element access style. You can read a more in-depth description of these in the :ref:`howToScanImagesOpenCV` tutorial. Converting from the old function names is easy. Just remove the cv prefix and use the new *Mat* data structure. Here's an example of this by using the weighted addition function:
.. literalinclude:: ../../../../samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp
:language: cpp
@ -105,7 +105,7 @@ Here you can observe that we may go through all the pixels of an image in three
:tab-width: 4
:lines: 79-112
As you may observe the *planes* variable is of type *Mat*. However, converting from *Mat* to *IplImage* is easy and made automatically with a simple assignment operator.
As you may observe the *planes* variable is of type *Mat*. However, converting from *Mat* to *IplImage* is easy and made automatically with a simple assignment operator.
.. literalinclude:: ../../../../samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp
:language: cpp
@ -113,20 +113,17 @@ As you may observe the *planes* variable is of type *Mat*. However, converting f
:tab-width: 4
:lines: 115-127
The new *imshow* highgui function accepts both the *Mat* and *IplImage* data structures. Compile and run the program and if the first image below is your input you may get either the first or second as output:
The new *imshow* highgui function accepts both the *Mat* and *IplImage* data structures. Compile and run the program and if the first image below is your input you may get either the first or second as output:
.. image:: images/outputInteropOpenCV1.jpg
:alt: The output of the sample
:align: center
You may observe a runtime instance of this on the `YouTube here <https://www.youtube.com/watch?v=qckm-zvo31w>`_ and you can :download:`download the source code from here <../../../../samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp>` or find it in the :file:`samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp` of the OpenCV source code library.
You may observe a runtime instance of this on the `YouTube here <https://www.youtube.com/watch?v=qckm-zvo31w>`_ and you can :download:`download the source code from here <../../../../samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp>` or find it in the :file:`samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp` of the OpenCV source code library.
.. raw:: html
<div align="center">
<iframe title="Interoperability with OpenCV 1" width="560" height="349" src="http://www.youtube.com/embed/qckm-zvo31w?rel=0&loop=1" frameborder="0" allowfullscreen align="middle"></iframe>
</div>

View File

@ -8,11 +8,11 @@ Mask operations on matrices are quite simple. The idea is that we recalculate ea
Our test case
=============
Let us consider the issue of an image contrast enhancement method. Basically we want to apply for every pixel of the image the following formula:
Let us consider the issue of an image contrast enhancement method. Basically we want to apply for every pixel of the image the following formula:
.. math::
I(i,j) = 5*I(i,j) - [ I(i-1,j) + I(i+1,j) + I(i,j-1) + I(i,j+1)]
I(i,j) = 5*I(i,j) - [ I(i-1,j) + I(i+1,j) + I(i,j-1) + I(i,j+1)]
\iff I(i,j)*M, \text{where }
M = \bordermatrix{ _i\backslash ^j & -1 & 0 & +1 \cr
@ -23,12 +23,12 @@ Let us consider the issue of an image contrast enhancement method. Basically we
The first notation is by using a formula, while the second is a compacted version of the first by using a mask. You use the mask by putting the center of the mask matrix (in the upper case noted by the zero-zero index) on the pixel you want to calculate and sum up the pixel values multiplied with the overlapped matrix values. It's the same thing, however in case of large matrices the latter notation is a lot easier to look over.
Now let us see how we can make this happen by using the basic pixel access method or by using the :filtering:`filter2D <filter2d>` function.
Now let us see how we can make this happen by using the basic pixel access method or by using the :filtering:`filter2D <filter2d>` function.
The Basic Method
================
Here's a function that will do this:
Here's a function that will do this:
.. code-block:: cpp
@ -49,7 +49,7 @@ Here's a function that will do this:
for(int i= nChannels;i < nChannels*(myImage.cols-1); ++i)
{
*output++ = saturate_cast<uchar>(5*current[i]
*output++ = saturate_cast<uchar>(5*current[i]
-current[i-nChannels] - current[i+nChannels] - previous[i] - next[i]);
}
}
@ -87,7 +87,7 @@ We'll use the plain C [] operator to access pixels. Because we need to access mu
for(int i= nChannels;i < nChannels*(myImage.cols-1); ++i)
{
*output++ = saturate_cast<uchar>(5*current[i]
*output++ = saturate_cast<uchar>(5*current[i]
-current[i-nChannels] - current[i+nChannels] - previous[i] - next[i]);
}
}
@ -96,7 +96,7 @@ On the borders of the image the upper notation results inexistent pixel location
.. code-block:: cpp
Result.row(0).setTo(Scalar(0)); // The top row
Result.row(0).setTo(Scalar(0)); // The top row
Result.row(Result.rows-1).setTo(Scalar(0)); // The bottom row
Result.col(0).setTo(Scalar(0)); // The left column
Result.col(Result.cols-1).setTo(Scalar(0)); // The right column
@ -108,19 +108,19 @@ Applying such filters are so common in image processing that in OpenCV there exi
.. code-block:: cpp
Mat kern = (Mat_<char>(3,3) << 0, -1, 0,
Mat kern = (Mat_<char>(3,3) << 0, -1, 0,
-1, 5, -1,
0, -1, 0);
Then call the :filtering:`filter2D <filter2d>` function specifying the input, the output image and the kernell to use:
Then call the :filtering:`filter2D <filter2d>` function specifying the input, the output image and the kernell to use:
.. code-block:: cpp
filter2D(I, K, I.depth(), kern );
filter2D(I, K, I.depth(), kern );
The function even has a fifth optional argument to specify the center of the kernel, and a sixth one for determining what to do in the regions where the operation is undefined (borders). Using this function has the advantage that it's shorter, less verbose and because there are some optimization techniques implemented it is usually faster than the *hand-coded method*. For example in my test while the second one took only 13 milliseconds the first took around 31 milliseconds. Quite some difference.
For example:
For example:
.. image:: images/resultMatMaskFilter2D.png
:alt: A sample output of the program
@ -128,7 +128,7 @@ For example:
You can download this source code from :download:`here <../../../../samples/cpp/tutorial_code/core/mat_mask_operations/mat_mask_operations.cpp>` or look in the OpenCV source code libraries sample directory at :file:`samples/cpp/tutorial_code/core/mat_mask_operations/mat_mask_operations.cpp`.
Check out an instance of running the program on our `YouTube channel <http://www.youtube.com/watch?v=7PF1tAU9se4>`_ .
Check out an instance of running the program on our `YouTube channel <http://www.youtube.com/watch?v=7PF1tAU9se4>`_ .
.. raw:: html

View File

@ -19,15 +19,15 @@ For example in the above image you can see that the mirror of the car is nothing
OpenCV has been around since 2001. In those days the library was built around a *C* interface and to store the image in the memory they used a C structure called *IplImage*. This is the one you'll see in most of the older tutorials and educational materials. The problem with this is that it brings to the table all the minuses of the C language. The biggest issue is the manual memory management. It builds on the assumption that the user is responsible for taking care of memory allocation and deallocation. While this is not a problem with smaller programs, once your code base grows it will be more of a struggle to handle all this rather than focusing on solving your development goal.
Luckily C++ came around and introduced the concept of classes making easier for the user through automatic memory management (more or less). The good news is that C++ is fully compatible with C so no compatibility issues can arise from making the change. Therefore, OpenCV 2.0 introduced a new C++ interface which offered a new way of doing things which means you do not need to fiddle with memory management, making your code concise (less to write, to achieve more). The main downside of the C++ interface is that many embedded development systems at the moment support only C. Therefore, unless you are targeting embedded platforms, there's no point to using the *old* methods (unless you're a masochist programmer and you're asking for trouble).
Luckily C++ came around and introduced the concept of classes making easier for the user through automatic memory management (more or less). The good news is that C++ is fully compatible with C so no compatibility issues can arise from making the change. Therefore, OpenCV 2.0 introduced a new C++ interface which offered a new way of doing things which means you do not need to fiddle with memory management, making your code concise (less to write, to achieve more). The main downside of the C++ interface is that many embedded development systems at the moment support only C. Therefore, unless you are targeting embedded platforms, there's no point to using the *old* methods (unless you're a masochist programmer and you're asking for trouble).
The first thing you need to know about *Mat* is that you no longer need to manually allocate its memory and release it as soon as you do not need it. While doing this is still a possibility, most of the OpenCV functions will allocate its output data manually. As a nice bonus if you pass on an already existing *Mat* object, which has already allocated the required space for the matrix, this will be reused. In other words we use at all times only as much memory as we need to perform the task.
*Mat* is basically a class with two data parts: the matrix header (containing information such as the size of the matrix, the method used for storing, at which address is the matrix stored, and so on) and a pointer to the matrix containing the pixel values (taking any dimensionality depending on the method chosen for storing) . The matrix header size is constant, however the size of the matrix itself may vary from image to image and usually is larger by orders of magnitude.
*Mat* is basically a class with two data parts: the matrix header (containing information such as the size of the matrix, the method used for storing, at which address is the matrix stored, and so on) and a pointer to the matrix containing the pixel values (taking any dimensionality depending on the method chosen for storing) . The matrix header size is constant, however the size of the matrix itself may vary from image to image and usually is larger by orders of magnitude.
OpenCV is an image processing library. It contains a large collection of image processing functions. To solve a computational challenge, most of the time you will end up using multiple functions of the library. Because of this, passing images to functions is a common practice. We should not forget that we are talking about image processing algorithms, which tend to be quite computational heavy. The last thing we want to do is further decrease the speed of your program by making unnecessary copies of potentially *large* images.
To tackle this issue OpenCV uses a reference counting system. The idea is that each *Mat* object has its own header, however the matrix may be shared between two instance of them by having their matrix pointers point to the same address. Moreover, the copy operators **will only copy the headers** and the pointer to the large matrix, not the data itself.
To tackle this issue OpenCV uses a reference counting system. The idea is that each *Mat* object has its own header, however the matrix may be shared between two instance of them by having their matrix pointers point to the same address. Moreover, the copy operators **will only copy the headers** and the pointer to the large matrix, not the data itself.
.. code-block:: cpp
:linenos:
@ -39,21 +39,21 @@ To tackle this issue OpenCV uses a reference counting system. The idea is that e
C = A; // Assignment operator
All the above objects, in the end, point to the same single data matrix. Their headers are different, however, and making a modification using any of them will affect all the other ones as well. In practice the different objects just provide different access method to the same underlying data. Nevertheless, their header parts are different. The real interesting part is that you can create headers which refer to only a subsection of the full data. For example, to create a region of interest (*ROI*) in an image you just create a new header with the new boundaries:
All the above objects, in the end, point to the same single data matrix. Their headers are different, however, and making a modification using any of them will affect all the other ones as well. In practice the different objects just provide different access method to the same underlying data. Nevertheless, their header parts are different. The real interesting part is that you can create headers which refer to only a subsection of the full data. For example, to create a region of interest (*ROI*) in an image you just create a new header with the new boundaries:
.. code-block:: cpp
:linenos:
Mat D (A, Rect(10, 10, 100, 100) ); // using a rectangle
Mat E = A(Range:all(), Range(1,3)); // using row and column boundaries
Mat E = A(Range:all(), Range(1,3)); // using row and column boundaries
Now you may ask if the matrix itself may belong to multiple *Mat* objects who takes responsibility for cleaning it up when it's no longer needed. The short answer is: the last object that used it. This is handled by using a reference counting mechanism. Whenever somebody copies a header of a *Mat* object, a counter is increased for the matrix. Whenever a header is cleaned this counter is decreased. When the counter reaches zero the matrix too is freed. Sometimes you will want to copy the matrix itself too, so OpenCV provides the :basicstructures:`clone() <mat-clone>` and :basicstructures:`copyTo() <mat-copyto>` functions.
.. code-block:: cpp
:linenos:
Mat F = A.clone();
Mat G;
Mat F = A.clone();
Mat G;
A.copyTo(G);
Now modifying *F* or *G* will not affect the matrix pointed by the *Mat* header. What you need to remember from all this is that:
@ -66,19 +66,19 @@ Now modifying *F* or *G* will not affect the matrix pointed by the *Mat* header.
* The underlying matrix of an image may be copied using the :basicstructures:`clone()<mat-clone>` and :basicstructures:`copyTo() <mat-copyto>` functions.
*Storing* methods
=================
=================
This is about how you store the pixel values. You can select the color space and the data type used. The color space refers to how we combine color components in order to code a given color. The simplest one is the gray scale where the colors at our disposal are black and white. The combination of these allows us to create many shades of gray.
This is about how you store the pixel values. You can select the color space and the data type used. The color space refers to how we combine color components in order to code a given color. The simplest one is the gray scale where the colors at our disposal are black and white. The combination of these allows us to create many shades of gray.
For *colorful* ways we have a lot more methods to choose from. Each of them breaks it down to three or four basic components and we can use the combination of these to create the others. The most popular one is RGB, mainly because this is also how our eye builds up colors. Its base colors are red, green and blue. To code the transparency of a color sometimes a fourth element: alpha (A) is added.
For *colorful* ways we have a lot more methods to choose from. Each of them breaks it down to three or four basic components and we can use the combination of these to create the others. The most popular one is RGB, mainly because this is also how our eye builds up colors. Its base colors are red, green and blue. To code the transparency of a color sometimes a fourth element: alpha (A) is added.
There are, however, many other color systems each with their own advantages:
.. container:: enumeratevisibleitemswithsquare
* RGB is the most common as our eyes use something similar, our display systems also compose colors using these.
* The HSV and HLS decompose colors into their hue, saturation and value/luminance components, which is a more natural way for us to describe colors. You might, for example, dismiss the last component, making your algorithm less sensible to the light conditions of the input image.
* YCrCb is used by the popular JPEG image format.
* The HSV and HLS decompose colors into their hue, saturation and value/luminance components, which is a more natural way for us to describe colors. You might, for example, dismiss the last component, making your algorithm less sensible to the light conditions of the input image.
* YCrCb is used by the popular JPEG image format.
* CIE L*a*b* is a perceptually uniform color space, which comes handy if you need to measure the *distance* of a given color to another color.
Each of the building components has their own valid domains. This leads to the data type used. How we store a component defines the control we have over its domain. The smallest data type possible is *char*, which means one byte or 8 bits. This may be unsigned (so can store values from 0 to 255) or signed (values from -127 to +127). Although in case of three components this already gives 16 million possible colors to represent (like in case of RGB) we may acquire an even finer control by using the float (4 byte = 32 bit) or double (8 byte = 64 bit) data types for each component. Nevertheless, remember that increasing the size of a component also increases the size of the whole picture in the memory.
@ -86,13 +86,13 @@ Each of the building components has their own valid domains. This leads to the d
Creating a *Mat* object explicitly
==================================
In the :ref:`Load_Save_Image` tutorial you have already learned how to write a matrix to an image file by using the :readWriteImageVideo:` imwrite() <imwrite>` function. However, for debugging purposes it's much more convenient to see the actual values. You can do this using the << operator of *Mat*. Be aware that this only works for two dimensional matrices.
In the :ref:`Load_Save_Image` tutorial you have already learned how to write a matrix to an image file by using the :readWriteImageVideo:` imwrite() <imwrite>` function. However, for debugging purposes it's much more convenient to see the actual values. You can do this using the << operator of *Mat*. Be aware that this only works for two dimensional matrices.
Although *Mat* works really well as an image container, it is also a general matrix class. Therefore, it is possible to create and manipulate multidimensional matrices. You can create a Mat object in multiple ways:
.. container:: enumeratevisibleitemswithsquare
+ :basicstructures:`Mat() <mat-mat>` Constructor
+ :basicstructures:`Mat() <mat-mat>` Constructor
.. literalinclude:: ../../../../samples/cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp
:language: cpp
@ -105,7 +105,7 @@ Although *Mat* works really well as an image container, it is also a general mat
For two dimensional and multichannel images we first define their size: row and column count wise.
Then we need to specify the data type to use for storing the elements and the number of channels per matrix point. To do this we have multiple definitions constructed according to the following convention:
Then we need to specify the data type to use for storing the elements and the number of channels per matrix point. To do this we have multiple definitions constructed according to the following convention:
.. code-block:: cpp
@ -176,7 +176,7 @@ Although *Mat* works really well as an image container, it is also a general mat
:alt: Demo image of the matrix output
:align: center
.. note::
.. note::
You can fill out a matrix with random values using the :operationsOnArrays:`randu() <randu>` function. You need to give the lower and upper value for the random values:
@ -189,11 +189,11 @@ Although *Mat* works really well as an image container, it is also a general mat
Output formatting
=================
In the above examples you could see the default formatting option. OpenCV, however, allows you to format your matrix output:
In the above examples you could see the default formatting option. OpenCV, however, allows you to format your matrix output:
.. container:: enumeratevisibleitemswithsquare
+ Default
+ Default
.. literalinclude:: ../../../../samples/cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp
:language: cpp
@ -215,7 +215,7 @@ In the above examples you could see the default formatting option. OpenCV, howev
:alt: Default Output
:align: center
+ Comma separated values (CSV)
+ Comma separated values (CSV)
.. literalinclude:: ../../../../samples/cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp
:language: cpp
@ -255,7 +255,7 @@ OpenCV offers support for output of other common OpenCV data structures too via
.. container:: enumeratevisibleitemswithsquare
+ 2D Point
+ 2D Point
.. literalinclude:: ../../../../samples/cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp
:language: cpp

View File

@ -44,7 +44,7 @@ Here you will learn the about the basic building blocks of the library. A must r
.. |HowScanImag| image:: images/howToScanImages.jpg
:height: 90pt
:width: 90pt
+
.. tabularcolumns:: m{100pt} m{300pt}
@ -193,7 +193,7 @@ Here you will learn the about the basic building blocks of the library. A must r
*Author:* |Author_BernatG|
Did you used OpenCV before its 2.0 version? Do you wanna know what happened with your library with 2.0? Don't you know how to convert your old OpenCV programs to the new C++ interface? Look here to shed light on all this questions.
=============== ======================================================
.. |InterOOpenCV1| image:: images/interopOpenCV1.png
@ -208,7 +208,7 @@ Here you will learn the about the basic building blocks of the library. A must r
.. toctree::
:hidden:
../mat_the_basic_image_container/mat_the_basic_image_container
../how_to_scan_images/how_to_scan_images
../mat-mask-operations/mat-mask-operations
@ -218,4 +218,4 @@ Here you will learn the about the basic building blocks of the library. A must r
../random_generator_and_text/random_generator_and_text
../discrete_fourier_transform/discrete_fourier_transform
../file_input_output_with_xml_yml/file_input_output_with_xml_yml
../interoperability_with_OpenCV_1/interoperability_with_OpenCV_1
../interoperability_with_OpenCV_1/interoperability_with_OpenCV_1

View File

@ -1 +1 @@
Include in this directory only defintion files. None of the reST files entered here will be parsed by the Sphinx Builder.
Include in this directory only defintion files. None of the reST files entered here will be parsed by the Sphinx Builder.

View File

@ -1,3 +1,3 @@
.. note::
Unfortunetly we have no tutorials into this section. And you can help us with that, since OpenCV is a community effort. If you have a tutorial suggestion or you have written a tutorial yourself (or coded a sample code) that you would like to see here, please contact follow these instructions: :ref:`howToWriteTutorial` and :how_to_contribute:`How to contribute <>`.
Unfortunetly we have no tutorials into this section. And you can help us with that, since OpenCV is a community effort. If you have a tutorial suggestion or you have written a tutorial yourself (or coded a sample code) that you would like to see here, please contact follow these instructions: :ref:`howToWriteTutorial` and :how_to_contribute:`How to contribute <>`.

View File

@ -3,7 +3,7 @@
.. |Author_AndreyK| unicode:: Andrey U+0020 Kamaev
.. |Author_LeonidBLB| unicode:: Leonid U+0020 Beynenson
.. |Author_VsevolodG| unicode:: Vsevolod U+0020 Glumov
.. |Author_VictorE| unicode:: Victor U+0020 Eruhimov
.. |Author_VictorE| unicode:: Victor U+0020 Eruhimov
.. |Author_ArtemM| unicode:: Artem U+0020 Myagkov
.. |Author_FernandoI| unicode:: Fernando U+0020 Iglesias U+0020 Garc U+00ED a
.. |Author_EduardF| unicode:: Eduard U+0020 Feicho

View File

@ -5,9 +5,9 @@ Detection of planar objects
.. highlight:: cpp
The goal of this tutorial is to learn how to use *features2d* and *calib3d* modules for detecting known planar objects in scenes.
The goal of this tutorial is to learn how to use *features2d* and *calib3d* modules for detecting known planar objects in scenes.
*Test data*: use images in your data folder, for instance, ``box.png`` and ``box_in_scene.png``.
*Test data*: use images in your data folder, for instance, ``box.png`` and ``box_in_scene.png``.
#.
Create a new console project. Read two input images. ::
@ -22,7 +22,7 @@ The goal of this tutorial is to learn how to use *features2d* and *calib3d* modu
FastFeatureDetector detector(15);
vector<KeyPoint> keypoints1;
detector.detect(img1, keypoints1);
... // do the same for the second image
#.
@ -32,7 +32,7 @@ The goal of this tutorial is to learn how to use *features2d* and *calib3d* modu
SurfDescriptorExtractor extractor;
Mat descriptors1;
extractor.compute(img1, keypoints1, descriptors1);
... // process keypoints from the second image as well
#.
@ -69,4 +69,4 @@ The goal of this tutorial is to learn how to use *features2d* and *calib3d* modu
perspectiveTransform(Mat(points1), points1Projected, H);
#.
Use ``drawMatches`` for drawing inliers.
Use ``drawMatches`` for drawing inliers.

View File

@ -100,6 +100,3 @@ Result
.. image:: images/Feature_Description_BruteForce_Result.jpg
:align: center
:height: 200pt

View File

@ -95,4 +95,3 @@ Result
.. image:: images/Feature_Detection_Result_b.jpg
:align: center
:height: 200pt

View File

@ -146,4 +146,3 @@ Result
.. image:: images/Feature_Homography_Result.jpg
:align: center
:height: 200pt

View File

@ -5,166 +5,166 @@
Learn about how to use the feature points detectors, descriptors and matching framework found inside OpenCV.
.. include:: ../../definitions/tocDefinitions.rst
.. include:: ../../definitions/tocDefinitions.rst
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|Harris| **Title:** :ref:`harris_detector`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Why is it a good idea to track corners? We learn to use the Harris method to detect corners
===================== ==============================================
.. |Harris| image:: images/trackingmotion/Harris_Detector_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|ShiTomasi| **Title:** :ref:`good_features_to_track`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we use an improved method to detect corners more accuratelyI
===================== ==============================================
.. |ShiTomasi| image:: images/trackingmotion/Shi_Tomasi_Detector_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|GenericCorner| **Title:** :ref:`generic_corner_detector`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Here you will learn how to use OpenCV functions to make your personalized corner detector!
===================== ==============================================
.. |GenericCorner| image:: images/trackingmotion/Generic_Corner_Detector_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|Subpixel| **Title:** :ref:`corner_subpixeles`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Is pixel resolution enough? Here we learn a simple method to improve our accuracy.
===================== ==============================================
.. |Subpixel| image:: images/trackingmotion/Corner_Subpixeles_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|FeatureDetect| **Title:** :ref:`feature_detection`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
In this tutorial, you will use *features2d* to detect interest points.
===================== ==============================================
.. |FeatureDetect| image:: images/Feature_Detection_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|FeatureDescript| **Title:** :ref:`feature_description`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
In this tutorial, you will use *features2d* to calculate feature vectors.
===================== ==============================================
.. |FeatureDescript| image:: images/Feature_Description_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|FeatureFlann| **Title:** :ref:`feature_flann_matcher`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
In this tutorial, you will use the FLANN library to make a fast matching.
===================== ==============================================
.. |FeatureFlann| image:: images/Feature_Flann_Matcher_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|FeatureHomo| **Title:** :ref:`feature_homography`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
In this tutorial, you will use *features2d* and *calib3d* to detect an object in a scene.
===================== ==============================================
.. |FeatureHomo| image:: images/Feature_Homography_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
@ -175,7 +175,7 @@ Learn about how to use the feature points detectors, descriptors and matching f
*Author:* |Author_VictorE|
You will use *features2d* and *calib3d* modules for detecting known planar objects in scenes.
You will use *features2d* and *calib3d* modules for detecting known planar objects in scenes.
===================== ==============================================
@ -201,4 +201,3 @@ Learn about how to use the feature points detectors, descriptors and matching f
../feature_flann_matcher/feature_flann_matcher
../feature_homography/feature_homography
../detection_of_planar_objects/detection_of_planar_objects

View File

@ -87,14 +87,14 @@ This tutorial code's is shown lines below. You can also download it from `here <
/// Apply corner detection
goodFeaturesToTrack( src_gray,
corners,
maxCorners,
qualityLevel,
minDistance,
Mat(),
blockSize,
useHarrisDetector,
k );
corners,
maxCorners,
qualityLevel,
minDistance,
Mat(),
blockSize,
useHarrisDetector,
k );
/// Draw corners detected
@ -135,4 +135,3 @@ Here is the result:
.. image:: images/Corner_Subpixeles_Result.jpg
:align: center

View File

@ -37,4 +37,3 @@ Result
.. image:: images/My_Shi_Tomasi_corner_detector_Result.jpg
:align: center

View File

@ -118,5 +118,3 @@ Result
.. image:: images/Feature_Detection_Result_a.jpg
:align: center

View File

@ -98,16 +98,16 @@ How does it work?
u & v
\end{bmatrix}
\left (
\displaystyle \sum_{x,y}
\displaystyle \sum_{x,y}
w(x,y)
\begin{bmatrix}
I_x^{2} & I_{x}I_{y} \\
I_xI_{y} & I_{y}^{2}
\end{bmatrix}
\right )
\begin{bmatrix}
\end{bmatrix}
\right )
\begin{bmatrix}
u \\
v
v
\end{bmatrix}
* Let's denote:
@ -115,11 +115,11 @@ How does it work?
.. math::
M = \displaystyle \sum_{x,y}
w(x,y)
\begin{bmatrix}
I_x^{2} & I_{x}I_{y} \\
I_xI_{y} & I_{y}^{2}
\end{bmatrix}
w(x,y)
\begin{bmatrix}
I_x^{2} & I_{x}I_{y} \\
I_xI_{y} & I_{y}^{2}
\end{bmatrix}
* So, our equation now is:
@ -128,10 +128,10 @@ How does it work?
E(u,v) \approx \begin{bmatrix}
u & v
\end{bmatrix}
M
\begin{bmatrix}
M
\begin{bmatrix}
u \\
v
v
\end{bmatrix}
@ -243,5 +243,3 @@ The detected corners are surrounded by a small black circle
.. image:: images/Harris_Detector_Result.jpg
:align: center

View File

@ -10,4 +10,3 @@ These tutorials are the bottom of the iceberg as they link together multiple of
.. raw:: latex
\pagebreak

View File

@ -7,7 +7,7 @@ Squeeze out every little computation power from your system by using the power o
.. include:: ../../definitions/tocDefinitions.rst
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
@ -18,7 +18,7 @@ Squeeze out every little computation power from your system by using the power o
*Author:* |Author_BernatG|
This will give a good grasp on how to approach coding on the GPU module, once you already know how to handle the other modules. As a test case it will port the similarity methods from the tutorial :ref:`videoInputPSNRMSSIM` to the GPU.
This will give a good grasp on how to approach coding on the GPU module, once you already know how to handle the other modules. As a test case it will port the similarity methods from the tutorial :ref:`videoInputPSNRMSSIM` to the GPU.
=============== ======================================================

View File

@ -3,30 +3,30 @@
*highgui* module. High Level GUI and Media
------------------------------------------
This section contains valuable tutorials about how to read/save your image/video files and how to use the built-in graphical user interface of the library.
This section contains valuable tutorials about how to read/save your image/video files and how to use the built-in graphical user interface of the library.
.. include:: ../../definitions/tocDefinitions.rst
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
=============== ======================================================
|Beginners_5| *Title:* :ref:`Adding_Trackbars`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
We will learn how to add a Trackbar to our applications
=============== ======================================================
.. |Beginners_5| image:: images/Adding_Trackbars_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
@ -34,7 +34,7 @@ This section contains valuable tutorials about how to read/save your image/video
|hVideoInput| *Title:* :ref:`videoInputPSNRMSSIM`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_BernatG|
You will learn how to read video streams, and how to calculate similarity values such as PSNR or SSIM.
@ -45,7 +45,7 @@ This section contains valuable tutorials about how to read/save your image/video
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
@ -74,4 +74,4 @@ This section contains valuable tutorials about how to read/save your image/video
../trackbar/trackbar
../video-input-psnr-ssim/video-input-psnr-ssim
../video-write/video-write
../video-write/video-write

View File

@ -5,11 +5,11 @@ Adding a Trackbar to our applications!
* In the previous tutorials (about *linear blending* and the *brightness and contrast adjustments*) you might have noted that we needed to give some **input** to our programs, such as :math:`\alpha` and :math:`beta`. We accomplished that by entering this data using the Terminal
* Well, it is time to use some fancy GUI tools. OpenCV provides some GUI utilities (*highgui.h*) for you. An example of this is a **Trackbar**
* Well, it is time to use some fancy GUI tools. OpenCV provides some GUI utilities (*highgui.h*) for you. An example of this is a **Trackbar**
.. image:: images/Adding_Trackbars_Tutorial_Trackbar.png
:alt: Trackbar example
:align: center
:align: center
* In this tutorial we will just modify our two previous programs so that they get the input information from the trackbar.
@ -19,7 +19,7 @@ Goals
In this tutorial you will learn how to:
* Add a Trackbar in an OpenCV window by using :create_trackbar:`createTrackbar <>`
* Add a Trackbar in an OpenCV window by using :create_trackbar:`createTrackbar <>`
Code
=====
@ -33,13 +33,13 @@ Let's modify the program made in the tutorial :ref:`Adding_Images`. We will let
using namespace cv;
/// Global Variables
/// Global Variables
const int alpha_slider_max = 100;
int alpha_slider;
int alpha_slider;
double alpha;
double beta;
double beta;
/// Matrices to store images
/// Matrices to store images
Mat src1;
Mat src2;
Mat dst;
@ -49,12 +49,12 @@ Let's modify the program made in the tutorial :ref:`Adding_Images`. We will let
* @brief Callback for trackbar
*/
void on_trackbar( int, void* )
{
{
alpha = (double) alpha_slider/alpha_slider_max ;
beta = ( 1.0 - alpha );
addWeighted( src1, alpha, src2, beta, 0.0, dst);
imshow( "Linear Blend", dst );
}
@ -67,7 +67,7 @@ Let's modify the program made in the tutorial :ref:`Adding_Images`. We will let
if( !src1.data ) { printf("Error loading src1 \n"); return -1; }
if( !src2.data ) { printf("Error loading src2 \n"); return -1; }
/// Initialize values
/// Initialize values
alpha_slider = 0;
/// Create Windows
@ -75,13 +75,13 @@ Let's modify the program made in the tutorial :ref:`Adding_Images`. We will let
/// Create Trackbars
char TrackbarName[50];
sprintf( TrackbarName, "Alpha x %d", alpha_slider_max );
sprintf( TrackbarName, "Alpha x %d", alpha_slider_max );
createTrackbar( TrackbarName, "Linear Blend", &alpha_slider, alpha_slider_max, on_trackbar );
/// Show some stuff
on_trackbar( alpha_slider, 0 );
/// Wait until user press some key
waitKey(0);
return 0;
@ -113,7 +113,7 @@ We only analyze the code that is related to Trackbar:
createTrackbar( TrackbarName, "Linear Blend", &alpha_slider, alpha_slider_max, on_trackbar );
Note the following:
* Our Trackbar has a label **TrackbarName**
* The Trackbar is located in the window named **"Linear Blend"**
* The Trackbar values will be in the range from :math:`0` to **alpha_slider_max** (the minimum limit is always **zero**).
@ -125,21 +125,21 @@ We only analyze the code that is related to Trackbar:
.. code-block:: cpp
void on_trackbar( int, void* )
{
{
alpha = (double) alpha_slider/alpha_slider_max ;
beta = ( 1.0 - alpha );
addWeighted( src1, alpha, src2, beta, 0.0, dst);
imshow( "Linear Blend", dst );
}
Note that:
* We use the value of **alpha_slider** (integer) to get a double value for **alpha**.
* We use the value of **alpha_slider** (integer) to get a double value for **alpha**.
* **alpha_slider** is updated each time the trackbar is displaced by the user.
* We define *src1*, *src2*, *dist*, *alpha*, *alpha_slider* and *beta* as global variables, so they can be used everywhere.
Result
=======
@ -147,15 +147,10 @@ Result
.. image:: images/Adding_Trackbars_Tutorial_Result_0.jpg
:alt: Adding Trackbars - Windows Linux
:align: center
:align: center
* As a manner of practice, you can also add 02 trackbars for the program made in :ref:`Basic_Linear_Transform`. One trackbar to set :math:`\alpha` and another for :math:`\beta`. The output might look like:
.. image:: images/Adding_Trackbars_Tutorial_Result_1.jpg
:alt: Adding Trackbars - Lena
:align: center
:align: center

View File

@ -64,7 +64,7 @@ Closing the video is automatic when the objects destructor is called. However, i
captRefrnc >> frameReference;
captUndTst.open(frameUnderTest);
The upper read operations will leave empty the *Mat* objects if no frame could be acquired (either cause the video stream was closed or you got to the end of the video file). We can check this with a simple if:
The upper read operations will leave empty the *Mat* objects if no frame could be acquired (either cause the video stream was closed or you got to the end of the video file). We can check this with a simple if:
.. code-block:: cpp
@ -111,7 +111,7 @@ Then the PSNR is expressed as:
PSNR = 10 \cdot \log_{10} \left( \frac{MAX_I^2}{MSE} \right)
Here the :math:`MAX_I^2` is the maximum valid value for a pixel. In case of the simple single byte image per pixel per channel this is 255. When two images are the same the MSE will give zero, resulting in an invalid divide by zero operation in the PSNR formula. In this case the PSNR is undefined and as we'll need to handle this case separately. The transition to a logarithmic scale is made because the pixel values have a very wide dynamic range. All this translated to OpenCV and a C++ function looks like:
Here the :math:`MAX_I^2` is the maximum valid value for a pixel. In case of the simple single byte image per pixel per channel this is 255. When two images are the same the MSE will give zero, resulting in an invalid divide by zero operation in the PSNR formula. In this case the PSNR is undefined and as we'll need to handle this case separately. The transition to a logarithmic scale is made because the pixel values have a very wide dynamic range. All this translated to OpenCV and a C++ function looks like:
.. code-block:: cpp
@ -136,13 +136,13 @@ Here the :math:`MAX_I^2` is the maximum valid value for a pixel. In case of the
}
}
Typically result values are anywhere between 30 and 50 for video compression, where higher is better. If the images significantly differ you'll get much lower ones like 15 and so. This similarity check is easy and fast to calculate, however in practice it may turn out somewhat inconsistent with human eye perception. The **structural similarity** algorithm aims to correct this.
Typically result values are anywhere between 30 and 50 for video compression, where higher is better. If the images significantly differ you'll get much lower ones like 15 and so. This similarity check is easy and fast to calculate, however in practice it may turn out somewhat inconsistent with human eye perception. The **structural similarity** algorithm aims to correct this.
Describing the methods goes well beyond the purpose of this tutorial. For that I invite you to read the article introducing it. Nevertheless, you can get a good image of it by looking at the OpenCV implementation below.
Describing the methods goes well beyond the purpose of this tutorial. For that I invite you to read the article introducing it. Nevertheless, you can get a good image of it by looking at the OpenCV implementation below.
.. seealso::
SSIM is described more in-depth in the: "Z. Wang, A. C. Bovik, H. R. Sheikh and E. P. Simoncelli, "Image quality assessment: From error visibility to structural similarity," IEEE Transactions on Image Processing, vol. 13, no. 4, pp. 600-612, Apr. 2004." article.
SSIM is described more in-depth in the: "Z. Wang, A. C. Bovik, H. R. Sheikh and E. P. Simoncelli, "Image quality assessment: From error visibility to structural similarity," IEEE Transactions on Image Processing, vol. 13, no. 4, pp. 600-612, Apr. 2004." article.
.. code-block:: cpp
@ -162,7 +162,7 @@ Describing the methods goes well beyond the purpose of this tutorial. For that I
/***********************PRELIMINARY COMPUTING ******************************/
Mat mu1, mu2; //
Mat mu1, mu2; //
GaussianBlur(I1, mu1, Size(11, 11), 1.5);
GaussianBlur(I2, mu2, Size(11, 11), 1.5);
@ -199,7 +199,7 @@ Describing the methods goes well beyond the purpose of this tutorial. For that I
return mssim;
}
This will return a similarity index for each channel of the image. This value is between zero and one, where one corresponds to perfect fit. Unfortunately, the many Gaussian blurring is quite costly, so while the PSNR may work in a real time like environment (24 frame per second) this will take significantly more than to accomplish similar performance results.
This will return a similarity index for each channel of the image. This value is between zero and one, where one corresponds to perfect fit. Unfortunately, the many Gaussian blurring is quite costly, so while the PSNR may work in a real time like environment (24 frame per second) this will take significantly more than to accomplish similar performance results.
Therefore, the source code presented at the start of the tutorial will perform the PSNR measurement for each frame, and the SSIM only for the frames where the PSNR falls below an input value. For visualization purpose we show both images in an OpenCV window and print the PSNR and MSSIM values to the console. Expect to see something like:
@ -207,7 +207,7 @@ Therefore, the source code presented at the start of the tutorial will perform t
:alt: A sample output
:align: center
You may observe a runtime instance of this on the `YouTube here <https://www.youtube.com/watch?v=iOcNljutOgg>`_.
You may observe a runtime instance of this on the `YouTube here <https://www.youtube.com/watch?v=iOcNljutOgg>`_.
.. raw:: html

View File

@ -112,21 +112,21 @@ This tutorial code's is shown lines below. You can also download it from `here <
/// Create Erosion Trackbar
createTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Erosion Demo",
&erosion_elem, max_elem,
Erosion );
&erosion_elem, max_elem,
Erosion );
createTrackbar( "Kernel size:\n 2n +1", "Erosion Demo",
&erosion_size, max_kernel_size,
Erosion );
&erosion_size, max_kernel_size,
Erosion );
/// Create Dilation Trackbar
createTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Dilation Demo",
&dilation_elem, max_elem,
Dilation );
&dilation_elem, max_elem,
Dilation );
createTrackbar( "Kernel size:\n 2n +1", "Dilation Demo",
&dilation_size, max_kernel_size,
Dilation );
&dilation_size, max_kernel_size,
Dilation );
/// Default start
Erosion( 0, 0 );
@ -145,8 +145,8 @@ This tutorial code's is shown lines below. You can also download it from `here <
else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; }
Mat element = getStructuringElement( erosion_type,
Size( 2*erosion_size + 1, 2*erosion_size+1 ),
Point( erosion_size, erosion_size ) );
Size( 2*erosion_size + 1, 2*erosion_size+1 ),
Point( erosion_size, erosion_size ) );
/// Apply the erosion operation
erode( src, erosion_dst, element );
@ -162,8 +162,8 @@ This tutorial code's is shown lines below. You can also download it from `here <
else if( dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; }
Mat element = getStructuringElement( dilation_type,
Size( 2*dilation_size + 1, 2*dilation_size+1 ),
Point( dilation_size, dilation_size ) );
Size( 2*dilation_size + 1, 2*dilation_size+1 ),
Point( dilation_size, dilation_size ) );
/// Apply the dilation operation
dilate( src, dilation_dst, element );
imshow( "Dilation Demo", dilation_dst );
@ -201,8 +201,8 @@ Explanation
else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; }
Mat element = getStructuringElement( erosion_type,
Size( 2*erosion_size + 1, 2*erosion_size+1 ),
Point( erosion_size, erosion_size ) );
Size( 2*erosion_size + 1, 2*erosion_size+1 ),
Point( erosion_size, erosion_size ) );
/// Apply the erosion operation
erode( src, erosion_dst, element );
imshow( "Erosion Demo", erosion_dst );
@ -216,17 +216,17 @@ Explanation
.. code-block:: cpp
Mat element = getStructuringElement( erosion_type,
Size( 2*erosion_size + 1, 2*erosion_size+1 ),
Point( erosion_size, erosion_size ) );
Mat element = getStructuringElement( erosion_type,
Size( 2*erosion_size + 1, 2*erosion_size+1 ),
Point( erosion_size, erosion_size ) );
We can choose any of three shapes for our kernel:
.. container:: enumeratevisibleitemswithsquare
+ Rectangular box: MORPH_RECT
+ Cross: MORPH_CROSS
+ Ellipse: MORPH_ELLIPSE
+ Rectangular box: MORPH_RECT
+ Cross: MORPH_CROSS
+ Ellipse: MORPH_ELLIPSE
Then, we just have to specify the size of our kernel and the *anchor point*. If not specified, it is assumed to be in the center.
@ -251,8 +251,8 @@ The code is below. As you can see, it is completely similar to the snippet of co
else if( dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; }
Mat element = getStructuringElement( dilation_type,
Size( 2*dilation_size + 1, 2*dilation_size+1 ),
Point( dilation_size, dilation_size ) );
Size( 2*dilation_size + 1, 2*dilation_size+1 ),
Point( dilation_size, dilation_size ) );
/// Apply the dilation operation
dilate( src, dilation_dst, element );
imshow( "Dilation Demo", dilation_dst );

View File

@ -94,7 +94,7 @@ Code
* Loads an image
* Convert the original to HSV format and separate only *Hue* channel to be used for the Histogram (using the OpenCV function :mix_channels:`mixChannels <>`)
* Let the user to enter the number of bins to be used in the calculation of the histogram.
* Calculate the histogram (and update it if the bins change) and the backprojection of the same image.
* Calculate the histogram (and update it if the bins change) and the backprojection of the same image.
* Display the backprojection and the histogram in windows.
* **Downloadable code**:

View File

@ -329,4 +329,3 @@ Result
.. image:: images/Histogram_Calculation_Result.jpg
:align: center

View File

@ -369,4 +369,3 @@ Results
.. image:: images/Template_Matching_Image_Result.jpg
:align: center

View File

@ -282,6 +282,3 @@ Result
:align: center
* Notice how the image is superposed to the black background on the edge regions.

View File

@ -290,4 +290,3 @@ We get the following result by using the Probabilistic Hough Line Transform:
:align: center
You may observe that the number of lines detected vary while you change the *threshold*. The explanation is sort of evident: If you establish a higher threshold, fewer lines will be detected (since you will need more points to declare a line detected).

View File

@ -124,34 +124,34 @@ Code
for( int j = 0; j < src.rows; j++ )
{ for( int i = 0; i < src.cols; i++ )
{
{
switch( ind )
{
case 0:
if( i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75 )
{
case 0:
if( i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75 )
{
map_x.at<float>(j,i) = 2*( i - src.cols*0.25 ) + 0.5 ;
map_y.at<float>(j,i) = 2*( j - src.rows*0.25 ) + 0.5 ;
}
else
{ map_x.at<float>(j,i) = 0 ;
map_y.at<float>(j,i) = 0 ;
map_x.at<float>(j,i) = 2*( i - src.cols*0.25 ) + 0.5 ;
map_y.at<float>(j,i) = 2*( j - src.rows*0.25 ) + 0.5 ;
}
else
{ map_x.at<float>(j,i) = 0 ;
map_y.at<float>(j,i) = 0 ;
}
break;
case 1:
map_x.at<float>(j,i) = i ;
map_y.at<float>(j,i) = src.rows - j ;
break;
case 1:
map_x.at<float>(j,i) = i ;
map_y.at<float>(j,i) = src.rows - j ;
break;
case 2:
map_x.at<float>(j,i) = src.cols - i ;
map_y.at<float>(j,i) = j ;
break;
map_x.at<float>(j,i) = src.cols - i ;
map_y.at<float>(j,i) = j ;
break;
case 3:
map_x.at<float>(j,i) = src.cols - i ;
map_y.at<float>(j,i) = src.rows - j ;
break;
map_x.at<float>(j,i) = src.cols - i ;
map_y.at<float>(j,i) = src.rows - j ;
break;
} // end of switch
}
}
}
ind++;
}
@ -241,34 +241,34 @@ Explanation
for( int j = 0; j < src.rows; j++ )
{ for( int i = 0; i < src.cols; i++ )
{
{
switch( ind )
{
case 0:
if( i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75 )
{
case 0:
if( i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75 )
{
map_x.at<float>(j,i) = 2*( i - src.cols*0.25 ) + 0.5 ;
map_y.at<float>(j,i) = 2*( j - src.rows*0.25 ) + 0.5 ;
}
else
{ map_x.at<float>(j,i) = 0 ;
map_y.at<float>(j,i) = 0 ;
map_x.at<float>(j,i) = 2*( i - src.cols*0.25 ) + 0.5 ;
map_y.at<float>(j,i) = 2*( j - src.rows*0.25 ) + 0.5 ;
}
else
{ map_x.at<float>(j,i) = 0 ;
map_y.at<float>(j,i) = 0 ;
}
break;
case 1:
map_x.at<float>(j,i) = i ;
map_y.at<float>(j,i) = src.rows - j ;
break;
case 1:
map_x.at<float>(j,i) = i ;
map_y.at<float>(j,i) = src.rows - j ;
break;
case 2:
map_x.at<float>(j,i) = src.cols - i ;
map_y.at<float>(j,i) = j ;
break;
map_x.at<float>(j,i) = src.cols - i ;
map_y.at<float>(j,i) = j ;
break;
case 3:
map_x.at<float>(j,i) = src.cols - i ;
map_y.at<float>(j,i) = src.rows - j ;
break;
map_x.at<float>(j,i) = src.cols - i ;
map_y.at<float>(j,i) = src.rows - j ;
break;
} // end of switch
}
}
}
ind++;
}
@ -311,4 +311,3 @@ Result
:alt: Result 0 for remapping
:width: 250pt
:align: center

View File

@ -306,4 +306,3 @@ Result
:alt: Original image
:width: 250pt
:align: center

View File

@ -154,13 +154,13 @@ This tutorial code's is shown lines below. You can also download it from `here <
/// Create Trackbar to select kernel type
createTrackbar( "Element:\n 0: Rect - 1: Cross - 2: Ellipse", window_name,
&morph_elem, max_elem,
Morphology_Operations );
&morph_elem, max_elem,
Morphology_Operations );
/// Create Trackbar to choose kernel size
createTrackbar( "Kernel size:\n 2n +1", window_name,
&morph_size, max_kernel_size,
Morphology_Operations );
&morph_size, max_kernel_size,
Morphology_Operations );
/// Default start
Morphology_Operations( 0, 0 );
@ -211,16 +211,16 @@ Explanation
.. code-block:: cpp
createTrackbar( "Element:\n 0: Rect - 1: Cross - 2: Ellipse", window_name,
&morph_elem, max_elem,
Morphology_Operations );
&morph_elem, max_elem,
Morphology_Operations );
* The final trackbar **"Kernel Size"** returns the size of the kernel to be used (**morph_size**)
.. code-block:: cpp
createTrackbar( "Kernel size:\n 2n +1", window_name,
&morph_size, max_kernel_size,
Morphology_Operations );
&morph_size, max_kernel_size,
Morphology_Operations );
* Every time we move any slider, the user's function **Morphology_Operations** will be called to effectuate a new morphology operation and it will update the output image based on the current trackbar values.
@ -279,4 +279,3 @@ Results
.. image:: images/Morphology_2_Tutorial_Cover.jpg
:alt: Morphology 2: Result sample
:align: center

View File

@ -259,5 +259,3 @@ Results
.. image:: images/Pyramids_Tutorial_PyrUp_Result.jpg
:alt: Pyramids: PyrUp Result
:align: center

View File

@ -121,4 +121,3 @@ Result
.. |BRC_1| image:: images/Bounding_Rects_Circles_Result.jpg
:align: middle

View File

@ -123,4 +123,3 @@ Result
.. |BRE_1| image:: images/Bounding_Rotated_Ellipses_Result.jpg
:align: middle

View File

@ -104,4 +104,3 @@ Result
.. |contour_1| image:: images/Find_Contours_Result.jpg
:align: middle

View File

@ -113,4 +113,3 @@ Result
.. |Hull_1| image:: images/Hull_Result.jpg
:align: middle

View File

@ -133,4 +133,3 @@ Result
.. |MU_2| image:: images/Moments_Result2.jpg
:width: 250pt
:align: middle

View File

@ -114,4 +114,3 @@ Result
.. |PPT_1| image:: images/Point_Polygon_Test_Result.jpg
:align: middle

View File

@ -7,502 +7,502 @@ In this section you will learn about the image processing (manipulation) functio
.. include:: ../../definitions/tocDefinitions.rst
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|ImageProcessing_1| **Title:** :ref:`Smoothing`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Let's take a look at some basic linear filters!
===================== ==============================================
.. |ImageProcessing_1| image:: images/Smoothing_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|ImageProcessing_2| **Title:** :ref:`Morphology_1`
*Compatibility:* > OpenCV 2.0
Author: |Author_AnaH|
Let's *change* the shape of objects!
===================== ==============================================
.. |ImageProcessing_2| image:: images/Morphology_1_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
================= ==================================================
|Morphology_2| **Title:** :ref:`Morphology_2`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Here we investigate different morphology operators
================= ==================================================
.. |Morphology_2| image:: images/Morphology_2_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|Pyramids| **Title:** :ref:`Pyramids`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
What if I need a bigger/smaller image?
===================== ==============================================
.. |Pyramids| image:: images/Pyramids_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|Threshold| **Title:** :ref:`Basic_Threshold`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
After so much processing, it is time to decide which pixels stay!
===================== ==============================================
.. |Threshold| image:: images/Threshold_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
+
+
===================== ==============================================
|Filter_2D| **Title:** :ref:`filter_2d`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn to design our own filters by using OpenCV functions
===================== ==============================================
.. |Filter_2D| image:: images/imgtrans/Filter_2D_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
+
+
===================== ==============================================
|CopyMakeBorder| **Title:** :ref:`copyMakeBorderTutorial`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn how to pad our images!
===================== ==============================================
.. |CopyMakeBorder| image:: images/imgtrans/CopyMakeBorder_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|SobelDerivatives| **Title:** :ref:`sobel_derivatives`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn how to calculate gradients and use them to detect edges!
===================== ==============================================
.. |SobelDerivatives| image:: images/imgtrans/Sobel_Derivatives_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|LaplaceOperator| **Title:** :ref:`laplace_operator`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn about the *Laplace* operator and how to detect edges with it.
===================== ==============================================
.. |LaplaceOperator| image:: images/imgtrans/Laplace_Operator_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|CannyDetector| **Title:** :ref:`canny_detector`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn a sophisticated alternative to detect edges.
===================== ==============================================
.. |CannyDetector| image:: images/imgtrans/Canny_Detector_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|HoughLines| **Title:** :ref:`hough_lines`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn how to detect lines
===================== ==============================================
.. |HoughLines| image:: images/imgtrans/Hough_Lines_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|HoughCircle| **Title:** :ref:`hough_circle`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn how to detect circles
===================== ==============================================
.. |HoughCircle| image:: images/imgtrans/Hough_Circle_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|Remap| **Title:** :ref:`remap`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn how to manipulate pixels locations
===================== ==============================================
.. |Remap| image:: images/imgtrans/Remap_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|WarpAffine| **Title:** :ref:`warp_affine`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn how to rotate, translate and scale our images
===================== ==============================================
.. |WarpAffine| image:: images/imgtrans/Warp_Affine_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|HistEqualization| **Title:** :ref:`histogram_equalization`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn how to improve the contrast in our images
===================== ==============================================
.. |HistEqualization| image:: images/histograms/Histogram_Equalization_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|HistCalculation| **Title:** :ref:`histogram_calculation`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn how to create and generate histograms
===================== ==============================================
.. |HistCalculation| image:: images/histograms/Histogram_Calculation_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|HistComparison| **Title:** :ref:`histogram_comparison`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn to calculate metrics between histograms
===================== ==============================================
.. |HistComparison| image:: images/histograms/Histogram_Comparison_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|BackProjection| **Title:** :ref:`back_projection`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn how to use histograms to find similar objects in images
===================== ==============================================
.. |BackProjection| image:: images/histograms/Back_Projection_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|TemplateMatching| **Title:** :ref:`template_matching`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn how to match templates in an image
===================== ==============================================
.. |TemplateMatching| image:: images/histograms/Template_Matching_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|FindContours| **Title:** :ref:`find_contours`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn how to find contours of objects in our image
===================== ==============================================
.. |FindContours| image:: images/shapedescriptors/Find_Contours_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|Hull| **Title:** :ref:`hull`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn how to get hull contours and draw them!
===================== ==============================================
.. |Hull| image:: images/shapedescriptors/Hull_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|BRC| **Title:** :ref:`bounding_rects_circles`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn how to obtain bounding boxes and circles for our contours.
===================== ==============================================
.. |BRC| image:: images/shapedescriptors/Bounding_Rects_Circles_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|BRE| **Title:** :ref:`bounding_rotated_ellipses`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn how to obtain rotated bounding boxes and ellipses for our contours.
===================== ==============================================
.. |BRE| image:: images/shapedescriptors/Bounding_Rotated_Ellipses_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|MU| **Title:** :ref:`moments`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn to calculate the moments of an image
===================== ==============================================
.. |MU| image:: images/shapedescriptors/Moments_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
+
+
.. tabularcolumns:: m{100pt} m{300pt}
.. cssclass:: toctableopencv
===================== ==============================================
|PPT| **Title:** :ref:`point_polygon_test`
*Compatibility:* > OpenCV 2.0
*Author:* |Author_AnaH|
Where we learn how to calculate distances from the image to contours
===================== ==============================================
.. |PPT| image:: images/shapedescriptors/Point_Polygon_Test_Tutorial_Cover.jpg
:height: 90pt
:width: 90pt
@ -539,6 +539,3 @@ In this section you will learn about the image processing (manipulation) functio
../shapedescriptors/bounding_rotated_ellipses/bounding_rotated_ellipses
../shapedescriptors/moments/moments
../shapedescriptors/point_polygon_test/point_polygon_test

View File

@ -174,12 +174,12 @@ The tutorial code's is shown lines below. You can also download it from `here <h
/// Create Trackbar to choose type of Threshold
createTrackbar( trackbar_type,
window_name, &threshold_type,
max_type, Threshold_Demo );
window_name, &threshold_type,
max_type, Threshold_Demo );
createTrackbar( trackbar_value,
window_name, &threshold_value,
max_value, Threshold_Demo );
window_name, &threshold_value,
max_value, Threshold_Demo );
/// Call the function to initialize
Threshold_Demo( 0, 0 );
@ -190,7 +190,7 @@ The tutorial code's is shown lines below. You can also download it from `here <h
int c;
c = waitKey( 20 );
if( (char)c == 27 )
{ break; }
{ break; }
}
}
@ -245,12 +245,12 @@ Explanation
.. code-block:: cpp
createTrackbar( trackbar_type,
window_name, &threshold_type,
max_type, Threshold_Demo );
window_name, &threshold_type,
max_type, Threshold_Demo );
createTrackbar( trackbar_value,
window_name, &threshold_value,
max_value, Threshold_Demo );
window_name, &threshold_value,
max_value, Threshold_Demo );
* Wait until the user enters the threshold value, the type of thresholding (or until the program exits)

View File

@ -6,7 +6,7 @@ Android Development with OpenCV
This tutorial has been created to help you use OpenCV library within your Android project.
This guide was written with Windows 7 in mind, though it should work with any other OS supported by
This guide was written with Windows 7 in mind, though it should work with any other OS supported by
OpenCV4Android SDK.
This tutorial assumes you have the following installed and configured:
@ -23,22 +23,22 @@ This tutorial assumes you have the following installed and configured:
If you need help with anything of the above, you may refer to our :ref:`android_dev_intro` guide.
This tutorial also assumes you have OpenCV4Android SDK already installed on your development
machine and OpenCV Manager on your testing device correspondingly. If you need help with any of
This tutorial also assumes you have OpenCV4Android SDK already installed on your development
machine and OpenCV Manager on your testing device correspondingly. If you need help with any of
these, you may consult our :ref:`O4A_SDK` tutorial.
If you encounter any error after thoroughly following these steps, feel free to contact us via
`OpenCV4Android <https://groups.google.com/group/android-opencv/>`_ discussion group or OpenCV
If you encounter any error after thoroughly following these steps, feel free to contact us via
`OpenCV4Android <https://groups.google.com/group/android-opencv/>`_ discussion group or OpenCV
`Q&A forum <http://answers.opencv.org>`_ . We'll do our best to help you out.
Using OpenCV Library Within Your Android Project
================================================
In this section we will explain how to make some existing project to use OpenCV.
Starting with 2.4.2 release for Android, *OpenCV Manager* is used to provide apps with the best
available version of OpenCV.
You can get more information here: :ref:`Android_OpenCV_Manager` and in these
In this section we will explain how to make some existing project to use OpenCV.
Starting with 2.4.2 release for Android, *OpenCV Manager* is used to provide apps with the best
available version of OpenCV.
You can get more information here: :ref:`Android_OpenCV_Manager` and in these
`slides <https://docs.google.com/a/itseez.com/presentation/d/1EO_1kijgBg_BsjNp2ymk-aarg-0K279_1VZRcPplSuk/present#slide=id.p>`_.
@ -48,31 +48,31 @@ Java
Application Development with Async Initialization
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Using async initialization is a **recommended** way for application development. It uses the OpenCV
Using async initialization is a **recommended** way for application development. It uses the OpenCV
Manager to access OpenCV libraries externally installed in the target system.
#. Add OpenCV library project to your workspace. Use menu
#. Add OpenCV library project to your workspace. Use menu
:guilabel:`File -> Import -> Existing project in your workspace`.
Press :guilabel:`Browse` button and locate OpenCV4Android SDK
Press :guilabel:`Browse` button and locate OpenCV4Android SDK
(:file:`OpenCV-2.4.6-android-sdk/sdk`).
.. image:: images/eclipse_opencv_dependency0.png
:alt: Add dependency from OpenCV library
:align: center
#. In application project add a reference to the OpenCV Java SDK in
#. In application project add a reference to the OpenCV Java SDK in
:guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.6``.
.. image:: images/eclipse_opencv_dependency1.png
:alt: Add dependency from OpenCV library
:align: center
In most cases OpenCV Manager may be installed automatically from Google Play. For the case, when
Google Play is not available, i.e. emulator, developer board, etc, you can install it manually
In most cases OpenCV Manager may be installed automatically from Google Play. For the case, when
Google Play is not available, i.e. emulator, developer board, etc, you can install it manually
using adb tool. See :ref:`manager_selection` for details.
There is a very base code snippet implementing the async initialization. It shows basic principles.
There is a very base code snippet implementing the async initialization. It shows basic principles.
See the "15-puzzle" OpenCV sample for details.
.. code-block:: java
@ -107,47 +107,47 @@ See the "15-puzzle" OpenCV sample for details.
...
}
It this case application works with OpenCV Manager in asynchronous fashion. ``OnManagerConnected``
callback will be called in UI thread, when initialization finishes. Please note, that it is not
allowed to use OpenCV calls or load OpenCV-dependent native libs before invoking this callback.
Load your own native libraries that depend on OpenCV after the successful OpenCV initialization.
Default ``BaseLoaderCallback`` implementation treat application context as Activity and calls
``Activity.finish()`` method to exit in case of initialization failure. To override this behavior
you need to override ``finish()`` method of ``BaseLoaderCallback`` class and implement your own
It this case application works with OpenCV Manager in asynchronous fashion. ``OnManagerConnected``
callback will be called in UI thread, when initialization finishes. Please note, that it is not
allowed to use OpenCV calls or load OpenCV-dependent native libs before invoking this callback.
Load your own native libraries that depend on OpenCV after the successful OpenCV initialization.
Default ``BaseLoaderCallback`` implementation treat application context as Activity and calls
``Activity.finish()`` method to exit in case of initialization failure. To override this behavior
you need to override ``finish()`` method of ``BaseLoaderCallback`` class and implement your own
finalization method.
Application Development with Static Initialization
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
According to this approach all OpenCV binaries are included into your application package. It is
designed mostly for development purposes. This approach is deprecated for the production code,
release package is recommended to communicate with OpenCV Manager via the async initialization
According to this approach all OpenCV binaries are included into your application package. It is
designed mostly for development purposes. This approach is deprecated for the production code,
release package is recommended to communicate with OpenCV Manager via the async initialization
described above.
#. Add the OpenCV library project to your workspace the same way as for the async initialization
above. Use menu :guilabel:`File -> Import -> Existing project in your workspace`,
press :guilabel:`Browse` button and select OpenCV SDK path
#. Add the OpenCV library project to your workspace the same way as for the async initialization
above. Use menu :guilabel:`File -> Import -> Existing project in your workspace`,
press :guilabel:`Browse` button and select OpenCV SDK path
(:file:`OpenCV-2.4.6-android-sdk/sdk`).
.. image:: images/eclipse_opencv_dependency0.png
:alt: Add dependency from OpenCV library
:align: center
#. In the application project add a reference to the OpenCV4Android SDK in
#. In the application project add a reference to the OpenCV4Android SDK in
:guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.6``;
.. image:: images/eclipse_opencv_dependency1.png
:alt: Add dependency from OpenCV library
:align: center
#. If your application project **doesn't have a JNI part**, just copy the corresponding OpenCV
#. If your application project **doesn't have a JNI part**, just copy the corresponding OpenCV
native libs from :file:`<OpenCV-2.4.6-android-sdk>/sdk/native/libs/<target_arch>` to your
project directory to folder :file:`libs/<target_arch>`.
In case of the application project **with a JNI part**, instead of manual libraries copying you
In case of the application project **with a JNI part**, instead of manual libraries copying you
need to modify your ``Android.mk`` file:
add the following two code lines after the ``"include $(CLEAR_VARS)"`` and before
add the following two code lines after the ``"include $(CLEAR_VARS)"`` and before
``"include path_to_OpenCV-2.4.6-android-sdk/sdk/native/jni/OpenCV.mk"``
.. code-block:: make
@ -168,13 +168,13 @@ described above.
OPENCV_INSTALL_MODULES:=on
include ../../sdk/native/jni/OpenCV.mk
After that the OpenCV libraries will be copied to your application :file:`libs` folder during
After that the OpenCV libraries will be copied to your application :file:`libs` folder during
the JNI build.v
Eclipse will automatically include all the libraries from the :file:`libs` folder to the
application package (APK).
Eclipse will automatically include all the libraries from the :file:`libs` folder to the
application package (APK).
#. The last step of enabling OpenCV in your application is Java initialization code before calling
#. The last step of enabling OpenCV in your application is Java initialization code before calling
OpenCV API. It can be done, for example, in the static section of the ``Activity`` class:
.. code-block:: java
@ -186,7 +186,7 @@ described above.
}
}
If you application includes other OpenCV-dependent native libraries you should load them
If you application includes other OpenCV-dependent native libraries you should load them
**after** OpenCV initialization:
.. code-block:: java
@ -205,16 +205,16 @@ described above.
Native/C++
----------
To build your own Android application, using OpenCV as native part, the following steps should be
To build your own Android application, using OpenCV as native part, the following steps should be
taken:
#. You can use an environment variable to specify the location of OpenCV package or just hardcode
#. You can use an environment variable to specify the location of OpenCV package or just hardcode
absolute or relative path in the :file:`jni/Android.mk` of your projects.
#. The file :file:`jni/Android.mk` should be written for the current application using the common
#. The file :file:`jni/Android.mk` should be written for the current application using the common
rules for this file.
For detailed information see the Android NDK documentation from the Android NDK archive, in the
For detailed information see the Android NDK documentation from the Android NDK archive, in the
file :file:`<path_where_NDK_is_placed>/docs/ANDROID-MK.html`.
#. The following line:
@ -229,7 +229,7 @@ taken:
include $(CLEAR_VARS)
#. Several variables can be used to customize OpenCV stuff, but you **don't need** to use them when
#. Several variables can be used to customize OpenCV stuff, but you **don't need** to use them when
your application uses the `async initialization` via the `OpenCV Manager` API.
.. note:: These variables should be set **before** the ``"include .../OpenCV.mk"`` line:
@ -238,7 +238,7 @@ taken:
OPENCV_INSTALL_MODULES:=on
Copies necessary OpenCV dynamic libs to the project ``libs`` folder in order to include them
Copies necessary OpenCV dynamic libs to the project ``libs`` folder in order to include them
into the APK.
.. code-block:: make
@ -251,7 +251,7 @@ taken:
OPENCV_LIB_TYPE:=STATIC
Perform static linking with OpenCV. By default dynamic link is used and the project JNI lib
Perform static linking with OpenCV. By default dynamic link is used and the project JNI lib
depends on ``libopencv_java.so``.
#. The file :file:`Application.mk` should exist and should contain lines:
@ -269,8 +269,8 @@ taken:
Should specify the application target platforms.
In some cases a linkage error (like ``"In function 'cv::toUtf16(std::basic_string<...>...
undefined reference to 'mbstowcs'"``) happens when building an application JNI library,
In some cases a linkage error (like ``"In function 'cv::toUtf16(std::basic_string<...>...
undefined reference to 'mbstowcs'"``) happens when building an application JNI library,
depending on OpenCV. The following line in the :file:`Application.mk` usually fixes it:
.. code-block:: make
@ -278,19 +278,19 @@ taken:
APP_PLATFORM := android-9
#. Either use :ref:`manual <NDK_build_cli>` ``ndk-build`` invocation or
:ref:`setup Eclipse CDT Builder <CDT_Builder>` to build native JNI lib before (re)building the Java
#. Either use :ref:`manual <NDK_build_cli>` ``ndk-build`` invocation or
:ref:`setup Eclipse CDT Builder <CDT_Builder>` to build native JNI lib before (re)building the Java
part and creating an APK.
Hello OpenCV Sample
===================
Here are basic steps to guide you trough the process of creating a simple OpenCV-centric
application. It will be capable of accessing camera output, processing it and displaying the
Here are basic steps to guide you trough the process of creating a simple OpenCV-centric
application. It will be capable of accessing camera output, processing it and displaying the
result.
#. Open Eclipse IDE, create a new clean workspace, create a new Android project
#. Open Eclipse IDE, create a new clean workspace, create a new Android project
:menuselection:`File --> New --> Android Project`
#. Set name, target, package and ``minSDKVersion`` accordingly. The minimal SDK version for build

View File

@ -384,4 +384,4 @@ upcoming issues. During this it may take a little longer to see your work online
however if you submitted it, be sure that eventually it will show up.
If you have any questions or advices relating to this tutorial you can contact us at
-delete-admin@-delete-opencv.org (delete the -delete- parts of that email address).
-delete-admin@-delete-opencv.org (delete the -delete- parts of that email address).

View File

@ -20,7 +20,7 @@ In MacOS it can be done using the following command in Terminal:
cd ~/<my_working _directory>
git clone https://github.com/Itseez/opencv.git
Building OpenCV from Source, using CMake and Command Line
=========================================================
@ -28,10 +28,10 @@ Building OpenCV from Source, using CMake and Command Line
#. Make symbolic link for Xcode to let OpenCV build scripts find the compiler, header files etc.
.. code-block:: bash
cd /
sudo ln -s /Applications/Xcode.app/Contents/Developer Developer
#. Build OpenCV framework:
.. code-block:: bash

View File

@ -11,7 +11,7 @@ Prerequisites
1. Having installed `Eclipse <http://www.eclipse.org/>`_ in your workstation (only the CDT plugin for C/C++ is needed). You can follow the following steps:
* Go to the Eclipse site
* Go to the Eclipse site
* Download `Eclipse IDE for C/C++ Developers <http://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers/heliossr2>`_ . Choose the link according to your workstation.
@ -20,7 +20,7 @@ Prerequisites
Making a project
=================
1. Start Eclipse. Just run the executable that comes in the folder.
1. Start Eclipse. Just run the executable that comes in the folder.
#. Go to **File -> New -> C/C++ Project**
@ -28,13 +28,13 @@ Making a project
:alt: Eclipse Tutorial Screenshot 0
:align: center
#. Choose a name for your project (i.e. DisplayImage). An **Empty Project** should be okay for this example.
#. Choose a name for your project (i.e. DisplayImage). An **Empty Project** should be okay for this example.
.. image:: images/a1.png
:alt: Eclipse Tutorial Screenshot 1
:align: center
#. Leave everything else by default. Press **Finish**.
#. Leave everything else by default. Press **Finish**.
#. Your project (in this case DisplayImage) should appear in the **Project Navigator** (usually at the left side of your window).
@ -45,7 +45,7 @@ Making a project
#. Now, let's add a source file using OpenCV:
* Right click on **DisplayImage** (in the Navigator). **New -> Folder** .
* Right click on **DisplayImage** (in the Navigator). **New -> Folder** .
.. image:: images/a4.png
:alt: Eclipse Tutorial Screenshot 4
@ -76,9 +76,9 @@ Making a project
image = imread( argv[1], 1 );
if( argc != 2 || !image.data )
{
{
printf( "No image data \n" );
return -1;
return -1;
}
namedWindow( "Display Image", CV_WINDOW_AUTOSIZE );
@ -102,7 +102,7 @@ Making a project
:align: center
.. note::
If you do not know where your opencv files are, open the **Terminal** and type:
If you do not know where your opencv files are, open the **Terminal** and type:
.. code-block:: bash
@ -112,56 +112,56 @@ Making a project
.. code-block:: bash
-I/usr/local/include/opencv -I/usr/local/include
-I/usr/local/include/opencv -I/usr/local/include
b. Now go to **GCC C++ Linker**,there you have to fill two spaces:
First in **Library search path (-L)** you have to write the path to where the opencv libraries reside, in my case the path is:
::
/usr/local/lib
Then in **Libraries(-l)** add the OpenCV libraries that you may need. Usually just the 3 first on the list below are enough (for simple applications) . In my case, I am putting all of them since I plan to use the whole bunch:
opencv_core
opencv_imgproc
opencv_core
opencv_imgproc
opencv_highgui
opencv_ml
opencv_video
opencv_ml
opencv_video
opencv_features2d
opencv_calib3d
opencv_objdetect
opencv_calib3d
opencv_objdetect
opencv_contrib
opencv_legacy
opencv_legacy
opencv_flann
.. image:: images/a10.png
:alt: Eclipse Tutorial Screenshot 10
:align: center
:align: center
If you don't know where your libraries are (or you are just psychotic and want to make sure the path is fine), type in **Terminal**:
.. code-block:: bash
pkg-config --libs opencv
My output (in case you want to check) was:
.. code-block:: bash
-L/usr/local/lib -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video -lopencv_features2d -lopencv_calib3d -lopencv_objdetect -lopencv_contrib -lopencv_legacy -lopencv_flann
-L/usr/local/lib -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video -lopencv_features2d -lopencv_calib3d -lopencv_objdetect -lopencv_contrib -lopencv_legacy -lopencv_flann
Now you are done. Click **OK**
* Your project should be ready to be built. For this, go to **Project->Build all**
* Your project should be ready to be built. For this, go to **Project->Build all**
In the Console you should get something like
In the Console you should get something like
.. image:: images/a12.png
:alt: Eclipse Tutorial Screenshot 12
:align: center
:align: center
If you check in your folder, there should be an executable there.
@ -179,21 +179,21 @@ So, now we have an executable ready to run. If we were to use the Terminal, we w
Assuming that the image to use as the argument would be located in <DisplayImage_directory>/images/HappyLittleFish.png. We can still do this, but let's do it from Eclipse:
#. Go to **Run->Run Configurations**
#. Go to **Run->Run Configurations**
#. Under C/C++ Application you will see the name of your executable + Debug (if not, click over C/C++ Application a couple of times). Select the name (in this case **DisplayImage Debug**).
#. Under C/C++ Application you will see the name of your executable + Debug (if not, click over C/C++ Application a couple of times). Select the name (in this case **DisplayImage Debug**).
#. Now, in the right side of the window, choose the **Arguments** Tab. Write the path of the image file we want to open (path relative to the workspace/DisplayImage folder). Let's use **HappyLittleFish.png**:
.. image:: images/a14.png
:alt: Eclipse Tutorial Screenshot 14
:align: center
:align: center
#. Click on the **Apply** button and then in Run. An OpenCV window should pop up with the fish image (or whatever you used).
.. image:: images/a15.jpg
:alt: Eclipse Tutorial Screenshot 15
:align: center
:align: center
#. Congratulations! You are ready to have fun with OpenCV using Eclipse.
@ -236,7 +236,7 @@ Say you have or create a new file, *helloworld.cpp* in a directory called *foo*:
ADD_EXECUTABLE( helloworld helloworld.cxx )
TARGET_LINK_LIBRARIES( helloworld ${OpenCV_LIBS} )
#. Run: ``cmake-gui ..`` and make sure you fill in where opencv was built.
#. Run: ``cmake-gui ..`` and make sure you fill in where opencv was built.
#. Then click ``configure`` and then ``generate``. If it's OK, **quit cmake-gui**
@ -253,6 +253,3 @@ Say you have or create a new file, *helloworld.cpp* in a directory called *foo*:
a. You can also optionally modify the ``Build command:`` from ``make`` to something like ``make VERBOSE=1 -j4`` which tells the compiler to produce detailed symbol files for debugging and also to compile in 4 parallel threads.
#. Done!

View File

@ -11,7 +11,7 @@ Using OpenCV with gcc and CMake
* The easiest way of using OpenCV in your code is to use `CMake <http://www.cmake.org/>`_. A few advantages (taken from the Wiki):
#. No need to change anything when porting between Linux and Windows
#. Can easily be combined with other tools by CMake( i.e. Qt, ITK and VTK )
#. Can easily be combined with other tools by CMake( i.e. Qt, ITK and VTK )
* If you are not familiar with CMake, checkout the `tutorial <http://www.cmake.org/cmake/help/cmake_tutorial.html>`_ on its website.
@ -21,7 +21,7 @@ Steps
Create a program using OpenCV
-------------------------------
Let's use a simple program such as DisplayImage.cpp shown below.
Let's use a simple program such as DisplayImage.cpp shown below.
.. code-block:: cpp
@ -36,9 +36,9 @@ Let's use a simple program such as DisplayImage.cpp shown below.
image = imread( argv[1], 1 );
if( argc != 2 || !image.data )
{
{
printf( "No image data \n" );
return -1;
return -1;
}
namedWindow( "Display Image", CV_WINDOW_AUTOSIZE );

View File

@ -11,8 +11,8 @@ Required Packages
.. code-block:: bash
sudo apt-get install build-essential
sudo apt-get install build-essential
* CMake 2.6 or higher;
* Git;
* GTK+2.x or higher, including headers (libgtk2.0-dev);
@ -48,7 +48,7 @@ In Linux it can be achieved with the following command in Terminal:
cd ~/<my_working _directory>
git clone https://github.com/Itseez/opencv.git
Building OpenCV from Source Using CMake, Using the Command Line
===============================================================
@ -58,26 +58,25 @@ Building OpenCV from Source Using CMake, Using the Command Line
#. Enter the <cmake_binary_dir> and type
.. code-block:: bash
cmake [<some optional parameters>] <path to the OpenCV source directory>
For example
.. code-block:: bash
cd ~/opencv
mkdir release
cd release
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..
#. Enter the created temporary directory (<cmake_binary_dir>) and proceed with:
.. code-block:: bash
make
sudo make install
.. note::
If the size of the created library is a critical issue (like in case of an Android build) you can use the ``install/strip`` command to get the smallest size as possible. The *stripped* version appears to be twice as small. However, we do not recommend using this unless those extra megabytes do really matter.
If the size of the created library is a critical issue (like in case of an Android build) you can use the ``install/strip`` command to get the smallest size as possible. The *stripped* version appears to be twice as small. However, we do not recommend using this unless those extra megabytes do really matter.

View File

@ -5,8 +5,8 @@ Load, Modify, and Save an Image
.. note::
We assume that by now you know how to load an image using :imread:`imread <>` and to display it in a window (using :imshow:`imshow <>`). Read the :ref:`Display_Image` tutorial otherwise.
We assume that by now you know how to load an image using :imread:`imread <>` and to display it in a window (using :imshow:`imshow <>`). Read the :ref:`Display_Image` tutorial otherwise.
Goals
======
@ -35,9 +35,9 @@ Here it is:
{
char* imageName = argv[1];
Mat image;
Mat image;
image = imread( imageName, 1 );
if( argc != 2 || !image.data )
{
printf( " No image data \n " );
@ -53,7 +53,7 @@ Here it is:
namedWindow( "Gray image", CV_WINDOW_AUTOSIZE );
imshow( imageName, image );
imshow( "Gray image", gray_image );
imshow( "Gray image", gray_image );
waitKey(0);
@ -67,18 +67,18 @@ Explanation
* Creating a Mat object to store the image information
* Load an image using :imread:`imread <>`, located in the path given by *imageName*. Fort this example, assume you are loading a RGB image.
#. Now we are going to convert our image from BGR to Grayscale format. OpenCV has a really nice function to do this kind of transformations:
#. Now we are going to convert our image from BGR to Grayscale format. OpenCV has a really nice function to do this kind of transformations:
.. code-block:: cpp
cvtColor( image, gray_image, CV_BGR2GRAY );
As you can see, :cvt_color:`cvtColor <>` takes as arguments:
.. container:: enumeratevisibleitemswithsquare
* a source image (*image*)
* a source image (*image*)
* a destination image (*gray_image*), in which we will save the converted image.
* an additional parameter that indicates what kind of transformation will be performed. In this case we use **CV_BGR2GRAY** (because of :imread:`imread <>` has BGR default channel order in case of color images).
@ -86,7 +86,7 @@ Explanation
.. code-block:: cpp
imwrite( "../../images/Gray_Image.jpg", gray_image );
imwrite( "../../images/Gray_Image.jpg", gray_image );
Which will save our *gray_image* as *Gray_Image.jpg* in the folder *images* located two levels up of my current location.

View File

@ -126,7 +126,7 @@ Building the library
#. Install |TortoiseGit|_. Choose the 32 or 64 bit version according to the type of OS you work in. While installing, locate your msysgit (if it doesn't do that automatically). Follow the wizard -- the default options are OK for the most part.
#. Choose a directory in your file system, where you will download the OpenCV libraries to. I recommend creating a new one that has short path and no special charachters in it, for example :file:`D:/OpenCV`. For this tutorial I'll suggest you do so. If you use your own path and know, what you're doing -- it's OK.
#. Choose a directory in your file system, where you will download the OpenCV libraries to. I recommend creating a new one that has short path and no special charachters in it, for example :file:`D:/OpenCV`. For this tutorial I'll suggest you do so. If you use your own path and know, what you're doing -- it's OK.
a) Clone the repository to the selected directory. After clicking *Clone* button, a window will appear where you can select from what repository you want to download source files (https://github.com/Itseez/opencv.git) and to what directory (:file:`D:/OpenCV`).
@ -314,10 +314,10 @@ First we set an enviroment variable to make easier our work. This will hold the
setx -m OPENCV_DIR D:\OpenCV\Build\x86\vc10 (suggested for Visual Studio 2010 - 32 bit Windows)
setx -m OPENCV_DIR D:\OpenCV\Build\x64\vc10 (suggested for Visual Studio 2010 - 64 bit Windows)
setx -m OPENCV_DIR D:\OpenCV\Build\x86\vc11 (suggested for Visual Studio 2012 - 32 bit Windows)
setx -m OPENCV_DIR D:\OpenCV\Build\x64\vc11 (suggested for Visual Studio 2012 - 64 bit Windows)
Here the directory is where you have your OpenCV binaries (*extracted* or *built*). You can have different platform (e.g. x64 instead of x86) or compiler type, so substitute appropriate value. Inside this you should have two folders called *lib* and *bin*. The -m should be added if you wish to make the settings computer wise, instead of user wise.
If you built static libraries then you are done. Otherwise, you need to add the *bin* folders path to the systems path. This is cause you will use the OpenCV library in form of *\"Dynamic-link libraries\"* (also known as **DLL**). Inside these are stored all the algorithms and information the OpenCV library contains. The operating system will load them only on demand, during runtime. However, to do this he needs to know where they are. The systems **PATH** contains a list of folders where DLLs can be found. Add the OpenCV library path to this and the OS will know where to look if he ever needs the OpenCV binaries. Otherwise, you will need to copy the used DLLs right beside the applications executable file (*exe*) for the OS to find it, which is highly unpleasent if you work on many projects. To do this start up again the |PathEditor|_ and add the following new entry (right click in the application to bring up the menu):

View File

@ -10,16 +10,16 @@ I start out from the assumption that you have read and completed with success th
:alt: You should have a folder looking like this.
:align: center
The OpenCV libraries, distributed by us, on the Microsoft Windows operating system are in a **D**\ ynamic **L**\ inked **L**\ ibraries (*DLL*). These have the advantage that all the content of the library are loaded only at runtime, on demand, and that countless programs may use the same library file. This means that if you have ten applications using the OpenCV library, no need to have around a version for each one of them. Of course you need to have the *dll* of the OpenCV on all systems where you want to run your application.
The OpenCV libraries, distributed by us, on the Microsoft Windows operating system are in a **D**\ ynamic **L**\ inked **L**\ ibraries (*DLL*). These have the advantage that all the content of the library are loaded only at runtime, on demand, and that countless programs may use the same library file. This means that if you have ten applications using the OpenCV library, no need to have around a version for each one of them. Of course you need to have the *dll* of the OpenCV on all systems where you want to run your application.
Another approach is to use static libraries that have *lib* extensions. You may build these by using our source files as described in the :ref:`Windows_Installation` tutorial. When you use this the library will be built-in inside your *exe* file. So there is no chance that the user deletes them, for some reason. As a drawback your application will be larger one and as, it will take more time to load it during its startup.
To build an application with OpenCV you need to do two things:
To build an application with OpenCV you need to do two things:
.. container:: enumeratevisibleitemswithsquare
+ *Tell* to the compiler how the OpenCV library *looks*. You do this by *showing* it the header files.
+ *Tell* to the linker from where to get the functions or data structures of OpenCV, when they are needed.
+ *Tell* to the compiler how the OpenCV library *looks*. You do this by *showing* it the header files.
+ *Tell* to the linker from where to get the functions or data structures of OpenCV, when they are needed.
If you use the *lib* system you must set the path where the library files are and specify in which one of them to look. During the build the linker will look into these libraries and add the definitions and implementation of all *used* functions and data structures to the executable file.
@ -27,7 +27,7 @@ To build an application with OpenCV you need to do two things:
To pass on all this information to the Visual Studio IDE you can either do it globally (so all your future projects will get these information) or locally (so only for you current project). The advantage of the global one is that you only need to do it once; however, it may be undesirable to clump all your projects all the time with all these information. In case of the global one how you do it depends on the Microsoft Visual Studio you use. There is a **2008 and previous versions** and a **2010 way** of doing it. Inside the global section of this tutorial I'll show what the main differences are.
The base item of a project in Visual Studio is a solution. A solution may contain multiple projects. Projects are the building blocks of an application. Every project will realize something and you will have a main project in which you can put together this project puzzle. In case of the many simple applications (like many of the tutorials will be) you do not need to break down the application into modules. In these cases your main project will be the only existing one. Now go create a new solution inside Visual studio by going through the :menuselection:`File --> New --> Project` menu selection. Choose *Win32 Console Application* as type. Enter its name and select the path where to create it. Then in the upcoming dialog make sure you create an empty project.
The base item of a project in Visual Studio is a solution. A solution may contain multiple projects. Projects are the building blocks of an application. Every project will realize something and you will have a main project in which you can put together this project puzzle. In case of the many simple applications (like many of the tutorials will be) you do not need to break down the application into modules. In these cases your main project will be the only existing one. Now go create a new solution inside Visual studio by going through the :menuselection:`File --> New --> Project` menu selection. Choose *Win32 Console Application* as type. Enter its name and select the path where to create it. Then in the upcoming dialog make sure you create an empty project.
.. image:: images/NewProjectVisualStudio.jpg
:alt: Which options to select
@ -36,7 +36,7 @@ The base item of a project in Visual Studio is a solution. A solution may contai
The *local* method
==================
Every project is built separately from the others. Due to this every project has its own rule package. Inside this rule packages are stored all the information the *IDE* needs to know to build your project. For any application there are at least two build modes: a *Release* and a *Debug* one. The *Debug* has many features that exist so you can find and resolve easier bugs inside your application. In contrast the *Release* is an optimized version, where the goal is to make the application run as fast as possible or to be as small as possible. You may figure that these modes also require different rules to use during build. Therefore, there exist different rule packages for each of your build modes. These rule packages are called inside the IDE as *project properties* and you can view and modify them by using the *Property Manger*. You can bring up this with :menuselection:`View --> Property Pages`. Expand it and you can see the existing rule packages (called *Proporty Sheets*).
Every project is built separately from the others. Due to this every project has its own rule package. Inside this rule packages are stored all the information the *IDE* needs to know to build your project. For any application there are at least two build modes: a *Release* and a *Debug* one. The *Debug* has many features that exist so you can find and resolve easier bugs inside your application. In contrast the *Release* is an optimized version, where the goal is to make the application run as fast as possible or to be as small as possible. You may figure that these modes also require different rules to use during build. Therefore, there exist different rule packages for each of your build modes. These rule packages are called inside the IDE as *project properties* and you can view and modify them by using the *Property Manger*. You can bring up this with :menuselection:`View --> Property Pages`. Expand it and you can see the existing rule packages (called *Proporty Sheets*).
.. image:: images/PropertyPageExample.jpg
:alt: An example of Property Sheet
@ -55,10 +55,10 @@ Use for example the *OpenCV_Debug* name. Then by selecting the sheet :menuselect
$(OPENCV_DIR)\..\..\include
.. image:: images/PropertySheetOpenCVInclude.jpg
:alt: Add the include dir like this.
:alt: Add the include dir like this.
:align: center
When adding third party libraries settings it is generally a good idea to use the power behind the environment variables. The full location of the OpenCV library may change on each system. Moreover, you may even end up yourself with moving the install directory for some reason. If you would give explicit paths inside your property sheet your project will end up not working when you pass it further to someone else who has a different OpenCV install path. Moreover, fixing this would require to manually modifying every explicit path. A more elegant solution is to use the environment variables. Anything that you put inside a parenthesis started with a dollar sign will be replaced at runtime with the current environment variables value. Here comes in play the environment variable setting we already made in our :ref:`previous tutorial <WindowsSetPathAndEnviromentVariable>`.
When adding third party libraries settings it is generally a good idea to use the power behind the environment variables. The full location of the OpenCV library may change on each system. Moreover, you may even end up yourself with moving the install directory for some reason. If you would give explicit paths inside your property sheet your project will end up not working when you pass it further to someone else who has a different OpenCV install path. Moreover, fixing this would require to manually modifying every explicit path. A more elegant solution is to use the environment variables. Anything that you put inside a parenthesis started with a dollar sign will be replaced at runtime with the current environment variables value. Here comes in play the environment variable setting we already made in our :ref:`previous tutorial <WindowsSetPathAndEnviromentVariable>`.
Next go to the :menuselection:`Linker --> General` and under the *"Additional Library Directories"* add the libs directory:
@ -67,7 +67,7 @@ Next go to the :menuselection:`Linker --> General` and under the *"Additional Li
$(OPENCV_DIR)\lib
.. image:: images/PropertySheetOpenCVLib.jpg
:alt: Add the library folder like this.
:alt: Add the library folder like this.
:align: center
Then you need to specify the libraries in which the linker should look into. To do this go to the :menuselection:`Linker --> Input` and under the *"Additional Dependencies"* entry add the name of all modules which you want to use:
@ -77,7 +77,7 @@ Then you need to specify the libraries in which the linker should look into. To
:align: center
.. image:: images/PropertySheetOpenCVLibrariesDebug.jpg
:alt: Like this.
:alt: Like this.
:align: center
The names of the libraries are as follow:
@ -105,33 +105,33 @@ A full list, for the latest version would contain:
The letter *d* at the end just indicates that these are the libraries required for the debug. Now click ok to save and do the same with a new property inside the Release rule section. Make sure to omit the *d* letters from the library names and to save the property sheets with the save icon above them.
.. image:: images/PropertySheetOpenCVLibrariesRelease.jpg
:alt: And the release ones.
:alt: And the release ones.
:align: center
You can find your property sheets inside your projects directory. At this point it is a wise decision to back them up into some special directory, to always have them at hand in the future, whenever you create an OpenCV project. Note that for Visual Studio 2010 the file extension is *props*, while for 2008 this is *vsprops*.
You can find your property sheets inside your projects directory. At this point it is a wise decision to back them up into some special directory, to always have them at hand in the future, whenever you create an OpenCV project. Note that for Visual Studio 2010 the file extension is *props*, while for 2008 this is *vsprops*.
.. image:: images/PropertySheetInsideFolder.jpg
:alt: And the release ones.
:alt: And the release ones.
:align: center
Next time when you make a new OpenCV project just use the "Add Existing Property Sheet..." menu entry inside the Property Manager to easily add the OpenCV build rules.
Next time when you make a new OpenCV project just use the "Add Existing Property Sheet..." menu entry inside the Property Manager to easily add the OpenCV build rules.
.. image:: images/PropertyPageAddExisting.jpg
:alt: Use this option.
:alt: Use this option.
:align: center
The *global* method
===================
In case you find to troublesome to add the property pages to each and every one of your projects you can also add this rules to a *"global property page"*. However, this applies only to the additional include and library directories. The name of the libraries to use you still need to specify manually by using for instance: a Property page.
In case you find to troublesome to add the property pages to each and every one of your projects you can also add this rules to a *"global property page"*. However, this applies only to the additional include and library directories. The name of the libraries to use you still need to specify manually by using for instance: a Property page.
In Visual Studio 2008 you can find this under the: :menuselection:`Tools --> Options --> Projects and Solutions --> VC++ Directories`.
In Visual Studio 2008 you can find this under the: :menuselection:`Tools --> Options --> Projects and Solutions --> VC++ Directories`.
.. image:: images/VCDirectories2008.jpg
:alt: VC++ Directories in VS 2008.
:align: center
In Visual Studio 2010 this has been moved to a global property sheet which is automatically added to every project you create:
In Visual Studio 2010 this has been moved to a global property sheet which is automatically added to every project you create:
.. image:: images/VCDirectories2010.jpg
:alt: VC++ Directories in VS 2010.
@ -153,10 +153,10 @@ You can start a Visual Studio build from two places. Either inside from the *IDE
.. |voila| unicode:: voil U+00E1
This is important to remember when you code inside the code open and save commands. You're resources will be saved ( and queried for at opening!!!) relatively to your working directory. This is unless you give a full, explicit path as parameter for the I/O functions. In the code above we open :download:`this OpenCV logo<../../../../samples/cpp/tutorial_code/images/opencv-logo.png>`. Before starting up the application make sure you place the image file in your current working directory. Modify the image file name inside the code to try it out on other images too. Run it and |voila|:
This is important to remember when you code inside the code open and save commands. You're resources will be saved ( and queried for at opening!!!) relatively to your working directory. This is unless you give a full, explicit path as parameter for the I/O functions. In the code above we open :download:`this OpenCV logo<../../../../samples/cpp/tutorial_code/images/opencv-logo.png>`. Before starting up the application make sure you place the image file in your current working directory. Modify the image file name inside the code to try it out on other images too. Run it and |voila|:
.. image:: images/SuccessVisualStudioWindows.jpg
:alt: You should have this.
:alt: You should have this.
:align: center
Command line arguments with Visual Studio
@ -167,11 +167,11 @@ Throughout some of our future tutorials you'll see that the programs main input
.. code-block:: bash
:linenos:
D:
D:
CD OpenCV\MySolutionName\Release
MySolutionName.exe exampleImage.jpg
Here I first changed my drive (if your project isn't on the OS local drive), navigated to my project and start it with an example image argument. While under Linux system it is common to fiddle around with the console window on the Microsoft Windows many people come to use it almost never. Besides, adding the same argument again and again while you are testing your application is, somewhat, a cumbersome task. Luckily, in the Visual Studio there is a menu to automate all this:
Here I first changed my drive (if your project isn't on the OS local drive), navigated to my project and start it with an example image argument. While under Linux system it is common to fiddle around with the console window on the Microsoft Windows many people come to use it almost never. Besides, adding the same argument again and again while you are testing your application is, somewhat, a cumbersome task. Luckily, in the Visual Studio there is a menu to automate all this:
.. image:: images/VisualStudioCommandLineArguments.jpg
:alt: Visual Studio Command Line Arguments

View File

@ -97,14 +97,14 @@ Now you can inspect the state of you program. For example, you can bring up the
Note that the built-in *Locals* window will display text only. This is where the Image Watch plug-in comes in. Image Watch is like another *Locals* window, but with an image viewer built into it. To bring up Image Watch, select :menuselection:`View --> Other Windows --> Image Watch`. Like Visual Studio's *Locals* window, Image Watch can dock to the Visual Studio IDE. Also, Visual Studio will remember whether you had Image Watch open, and where it was located between debugging sessions. This means you only have to do this once--the next time you start debugging, Image Watch will be back where you left it. Here's what the docked Image Watch window looks like at our breakpoint:
.. image:: images/toolwindow.jpg
:height: 320pt
:height: 320pt
The radio button at the top left (*Locals/Watch*) selects what is shown in the *Image List* below: *Locals* lists all OpenCV image objects in the current scope (this list is automatically populated). *Watch* shows image expressions that have been pinned for continuous inspection (not described here, see `Image Watch documentation <http://go.microsoft.com/fwlink/?LinkId=285461>`_ for details). The image list shows basic information such as width, height, number of channels, and, if available, a thumbnail. In our example, the image list contains our two local image variables, *input* and *edges*.
If an image has a thumbnail, left-clicking on that image will select it for detailed viewing in the *Image Viewer* on the right. The viewer lets you pan (drag mouse) and zoom (mouse wheel). It also displays the pixel coordinate and value at the current mouse position.
.. image:: images/viewer.jpg
:height: 160pt
:height: 160pt
Note that the second image in the list, *edges*, is shown as "invalid". This indicates that some data members of this image object have corrupt or invalid values (for example, a negative image width). This is expected at this point in the program, since the C++ constructor for *edges* has not run yet, and so its members have undefined values (in debug mode they are usually filled with "0xCD" bytes).
@ -113,18 +113,18 @@ From here you can single-step through your code (:menuselection:`Debug->Step Ove
Now assume you want to do a visual sanity check of the *cv::Canny()* implementation. Bring the *edges* image into the viewer by selecting it in the *Image List* and zoom into a region with a clearly defined edge:
.. image:: images/edges_zoom.png
:height: 160pt
:height: 160pt
Right-click on the *Image Viewer* to bring up the view context menu and enable :menuselection:`Link Views` (a check box next to the menu item indicates whether the option is enabled).
.. image:: images/viewer_context_menu.png
:height: 120pt
:height: 120pt
The :menuselection:`Link Views` feature keeps the view region fixed when flipping between images of the same size. To see how this works, select the input image from the image list--you should now see the corresponding zoomed-in region in the input image:
.. image:: images/input_zoom.png
:height: 160pt
:height: 160pt
You may also switch back and forth between viewing input and edges with your up/down cursor keys. That way you can easily verify that the detected edges line up nicely with the data in the input image.
More ...
@ -141,4 +141,4 @@ Image watch has a number of more advanced features, such as
Please refer to the online `Image Watch Documentation <http://go.microsoft.com/fwlink/?LinkId=285461>`_ for details--you also can get to the documentation page by clicking on the *Help* link in the Image Watch window:
.. image:: images/help_button.jpg
:height: 80pt
:height: 80pt

View File

@ -19,7 +19,7 @@ Follow this step by step guide to link OpenCV to iOS.
1. Create a new XCode project.
2. Now we need to link *opencv2.framework* with Xcode. Select the project Navigator in the left hand panel and click on project name.
2. Now we need to link *opencv2.framework* with Xcode. Select the project Navigator in the left hand panel and click on project name.
3. Under the TARGETS click on Build Phases. Expand Link Binary With Libraries option.
@ -29,10 +29,10 @@ Follow this step by step guide to link OpenCV to iOS.
.. image:: images/linking_opencv_ios.png
:alt: OpenCV iOS in Xcode
:align: center
:align: center
*Hello OpenCV iOS Application*
===============================
===============================
Now we will learn how to write a simple Hello World Application in Xcode using OpenCV.
@ -43,13 +43,13 @@ Now we will learn how to write a simple Hello World Application in Xcode using O
.. code-block:: cpp
#ifdef __cplusplus
#import <opencv2/opencv.hpp>
#endif
#ifdef __cplusplus
#import <opencv2/opencv.hpp>
#endif
.. image:: images/header_directive.png
:alt: header
:align: center
:align: center
.. container:: enumeratevisibleitemswithsquare
@ -61,7 +61,7 @@ Now we will learn how to write a simple Hello World Application in Xcode using O
.. image:: images/view_did_load.png
:alt: view did load
:align: center
:align: center
.. container:: enumeratevisibleitemswithsquare
@ -73,4 +73,3 @@ Now we will learn how to write a simple Hello World Application in Xcode using O
.. image:: images/output.png
:alt: output
:align: center

View File

@ -21,9 +21,9 @@ In *OpenCV* all the image processing operations are done on *Mat*. iOS uses UIIm
CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage);
CGFloat cols = image.size.width;
CGFloat rows = image.size.height;
cv::Mat cvMat(rows, cols, CV_8UC4); // 8 bits per component, 4 channels
CGContextRef contextRef = CGBitmapContextCreate(cvMat.data, // Pointer to data
cols, // Width of bitmap
rows, // Height of bitmap
@ -32,11 +32,11 @@ In *OpenCV* all the image processing operations are done on *Mat*. iOS uses UIIm
colorSpace, // Colorspace
kCGImageAlphaNoneSkipLast |
kCGBitmapByteOrderDefault); // Bitmap info flags
CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage);
CGContextRelease(contextRef);
CGColorSpaceRelease(colorSpace);
return cvMat;
}
@ -47,9 +47,9 @@ In *OpenCV* all the image processing operations are done on *Mat*. iOS uses UIIm
CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage);
CGFloat cols = image.size.width;
CGFloat rows = image.size.height;
cv::Mat cvMat(rows, cols, CV_8UC1); // 8 bits per component, 1 channels
CGContextRef contextRef = CGBitmapContextCreate(cvMat.data, // Pointer to data
cols, // Width of bitmap
rows, // Height of bitmap
@ -58,11 +58,11 @@ In *OpenCV* all the image processing operations are done on *Mat*. iOS uses UIIm
colorSpace, // Colorspace
kCGImageAlphaNoneSkipLast |
kCGBitmapByteOrderDefault); // Bitmap info flags
CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage);
CGContextRelease(contextRef);
CGColorSpaceRelease(colorSpace);
return cvMat;
}
@ -81,15 +81,15 @@ After the processing we need to convert it back to UIImage.
{
NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize()*cvMat.total()];
CGColorSpaceRef colorSpace;
if (cvMat.elemSize() == 1) {
colorSpace = CGColorSpaceCreateDeviceGray();
} else {
colorSpace = CGColorSpaceCreateDeviceRGB();
}
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
// Creating CGImage from cv::Mat
CGImageRef imageRef = CGImageCreate(cvMat.cols, //width
cvMat.rows, //height
@ -103,15 +103,15 @@ After the processing we need to convert it back to UIImage.
false, //should interpolate
kCGRenderingIntentDefault //intent
);
// Getting UIImage from CGImage
UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
return finalImage;
return finalImage;
}
*Output*
@ -119,12 +119,12 @@ After the processing we need to convert it back to UIImage.
.. image:: images/output.jpg
:alt: header
:align: center
:align: center
Check out an instance of running code with more Image Effects on `YouTube <http://www.youtube.com/watch?v=Ko3K_xdhJ1I>`_ .
Check out an instance of running code with more Image Effects on `YouTube <http://www.youtube.com/watch?v=Ko3K_xdhJ1I>`_ .
.. raw:: html
<div align="center">
<iframe width="560" height="350" src="http://www.youtube.com/embed/Ko3K_xdhJ1I" frameborder="0" allowfullscreen></iframe>
</div>
</div>

View File

@ -69,7 +69,7 @@
.. toctree::
:hidden:
../hello/hello
../image_manipulation/image_manipulation
../video_processing/video_processing

View File

@ -17,35 +17,35 @@ Including OpenCV library in your iOS project
The OpenCV library comes as a so-called framework, which you can directly drag-and-drop into your XCode project. Download the latest binary from <http://sourceforge.net/projects/opencvlibrary/files/opencv-ios/>. Alternatively follow this guide :ref:`iOS-Installation` to compile the framework manually. Once you have the framework, just drag-and-drop into XCode:
.. image:: images/xcode_hello_ios_framework_drag_and_drop.png
.. image:: images/xcode_hello_ios_framework_drag_and_drop.png
Also you have to locate the prefix header that is used for all header files in the project. The file is typically located at "ProjectName/Supporting Files/ProjectName-Prefix.pch". There, you have add an include statement to import the opencv library. However, make sure you include opencv before you include UIKit and Foundation, because else you will get some weird compile errors that some macros like min and max are defined multiple times. For example the prefix header could look like the following:
.. code-block:: objc
:linenos:
//
// Prefix header for all source files of the 'VideoFilters' target in the 'VideoFilters' project
//
#import <Availability.h>
#ifndef __IPHONE_4_0
#warning "This project uses features only available in iOS SDK 4.0 and later."
#endif
#ifdef __cplusplus
#import <opencv2/opencv.hpp>
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif
:linenos:
//
// Prefix header for all source files of the 'VideoFilters' target in the 'VideoFilters' project
//
#import <Availability.h>
#ifndef __IPHONE_4_0
#warning "This project uses features only available in iOS SDK 4.0 and later."
#endif
#ifdef __cplusplus
#import <opencv2/opencv.hpp>
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif
Example video frame processing project
--------------------------------------
User Interface
@ -53,63 +53,63 @@ User Interface
First, we create a simple iOS project, for example Single View Application. Then, we create and add an UIImageView and UIButton to start the camera and display the video frames. The storyboard could look like that:
.. image:: images/xcode_hello_ios_viewcontroller_layout.png
.. image:: images/xcode_hello_ios_viewcontroller_layout.png
Make sure to add and connect the IBOutlets and IBActions to the corresponding ViewController:
.. code-block:: objc
:linenos:
@interface ViewController : UIViewController
{
IBOutlet UIImageView* imageView;
IBOutlet UIButton* button;
}
- (IBAction)actionStart:(id)sender;
@end
:linenos:
@interface ViewController : UIViewController
{
IBOutlet UIImageView* imageView;
IBOutlet UIButton* button;
}
- (IBAction)actionStart:(id)sender;
@end
Adding the Camera
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We add a camera controller to the view controller and initialize it when the view has loaded:
.. code-block:: objc
:linenos:
#import <opencv2/highgui/cap_ios.h>
using namespace cv;
@interface ViewController : UIViewController
{
...
CvVideoCamera* videoCamera;
}
...
@property (nonatomic, retain) CvVideoCamera* videoCamera;
@end
.. code-block:: objc
:linenos:
:linenos:
#import <opencv2/highgui/cap_ios.h>
using namespace cv;
@interface ViewController : UIViewController
{
...
CvVideoCamera* videoCamera;
}
...
@property (nonatomic, retain) CvVideoCamera* videoCamera;
@end
.. code-block:: objc
:linenos:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.videoCamera = [[CvVideoCamera alloc] initWithParentView:imageView];
self.videoCamera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionFront;
self.videoCamera.defaultAVCaptureSessionPreset = AVCaptureSessionPreset352x288;
self.videoCamera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait;
self.videoCamera.defaultFPS = 30;
self.videoCamera.grayscale = NO;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.videoCamera = [[CvVideoCamera alloc] initWithParentView:imageView];
self.videoCamera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionFront;
self.videoCamera.defaultAVCaptureSessionPreset = AVCaptureSessionPreset352x288;
self.videoCamera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait;
self.videoCamera.defaultFPS = 30;
self.videoCamera.grayscale = NO;
}
In this case, we initialize the camera and provide the imageView as a target for rendering each frame. CvVideoCamera is basically a wrapper around AVFoundation, so we provie as properties some of the AVFoundation camera options. For example we want to use the front camera, set the video size to 352x288 and a video orientation (the video camera normally outputs in landscape mode, which results in transposed data when you design a portrait application).
The property defaultFPS sets the FPS of the camera. If the processing is less fast than the desired FPS, frames are automatically dropped.
@ -143,7 +143,7 @@ Additionally, we have to manually add framework dependencies of the opencv frame
* Foundation
.. image:: images/xcode_hello_ios_frameworks_add_dependencies.png
.. image:: images/xcode_hello_ios_frameworks_add_dependencies.png
Processing frames
@ -152,35 +152,35 @@ Processing frames
We follow the delegation pattern, which is very common in iOS, to provide access to each camera frame. Basically, the View Controller has to implement the CvVideoCameraDelegate protocol and has to be set as delegate to the video camera:
.. code-block:: objc
:linenos:
@interface ViewController : UIViewController<CvVideoCameraDelegate>
:linenos:
@interface ViewController : UIViewController<CvVideoCameraDelegate>
.. code-block:: objc
:linenos:
- (void)viewDidLoad
{
...
self.videoCamera = [[CvVideoCamera alloc] initWithParentView:imageView];
self.videoCamera.delegate = self;
...
}
:linenos:
- (void)viewDidLoad
{
...
self.videoCamera = [[CvVideoCamera alloc] initWithParentView:imageView];
self.videoCamera.delegate = self;
...
}
.. code-block:: objc
:linenos:
:linenos:
#pragma mark - Protocol CvVideoCameraDelegate
#pragma mark - Protocol CvVideoCameraDelegate
#ifdef __cplusplus
- (void)processImage:(Mat&)image;
{
// Do some OpenCV stuff with the image
}
#endif
#ifdef __cplusplus
- (void)processImage:(Mat&)image;
{
// Do some OpenCV stuff with the image
}
#endif
Note that we are using C++ here (cv::Mat).
Important: You have to rename the view controller's extension .m into .mm, so that the compiler compiles it under the assumption of Objective-C++ (Objective-C and C++ mixed). Then, __cplusplus is defined when the compiler is processing the file for C++ code. Therefore, we put our code within a block where __cplusplus is defined.
@ -193,18 +193,18 @@ From here you can start processing video frames. For example the following snipp
.. code-block:: objc
:linenos:
- (void)processImage:(Mat&)image;
{
// Do some OpenCV stuff with the image
Mat image_copy;
cvtColor(image, image_copy, CV_BGRA2BGR);
// invert image
bitwise_not(image_copy, image_copy);
cvtColor(image_copy, image, CV_BGR2BGRA);
}
:linenos:
- (void)processImage:(Mat&)image;
{
// Do some OpenCV stuff with the image
Mat image_copy;
cvtColor(image, image_copy, CV_BGRA2BGR);
// invert image
bitwise_not(image_copy, image_copy);
cvtColor(image_copy, image, CV_BGR2BGRA);
}
Start!
@ -213,14 +213,14 @@ Start!
Finally, we have to tell the camera to actually start/stop working. The following code will start the camera when you press the button, assuming you connected the UI properly:
.. code-block:: objc
:linenos:
#pragma mark - UI Actions
- (IBAction)actionStart:(id)sender;
{
[self.videoCamera start];
}
:linenos:
#pragma mark - UI Actions
- (IBAction)actionStart:(id)sender;
{
[self.videoCamera start];
}

Some files were not shown because too many files have changed in this diff Show More