mirror of
https://github.com/opencv/opencv.git
synced 2024-11-30 06:10:02 +08:00
Merge pull request #12894 from alalek:c_api_drop_samples
This commit is contained in:
commit
e959f449ae
@ -2,7 +2,7 @@ File Input and Output using XML and YAML files {#tutorial_file_input_output_with
|
||||
==============================================
|
||||
|
||||
@prev_tutorial{tutorial_discrete_fourier_transform}
|
||||
@next_tutorial{tutorial_interoperability_with_OpenCV_1}
|
||||
@next_tutorial{tutorial_how_to_use_OpenCV_parallel_for_}
|
||||
|
||||
Goal
|
||||
----
|
||||
|
@ -1,7 +1,7 @@
|
||||
How to use the OpenCV parallel_for_ to parallelize your code {#tutorial_how_to_use_OpenCV_parallel_for_}
|
||||
==================================================================
|
||||
|
||||
@prev_tutorial{tutorial_interoperability_with_OpenCV_1}
|
||||
@prev_tutorial{tutorial_file_input_output_with_xml_yml}
|
||||
|
||||
Goal
|
||||
----
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 25 KiB |
@ -1,143 +0,0 @@
|
||||
Interoperability with OpenCV 1 {#tutorial_interoperability_with_OpenCV_1}
|
||||
==============================
|
||||
|
||||
@prev_tutorial{tutorial_file_input_output_with_xml_yml}
|
||||
@next_tutorial{tutorial_how_to_use_OpenCV_parallel_for_}
|
||||
|
||||
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:
|
||||
|
||||
- What changed with the version 2 of OpenCV in the way you use the library compared to its first
|
||||
version
|
||||
- How to add some Gaussian noise to an image
|
||||
- What are lookup tables and why use them?
|
||||
|
||||
General
|
||||
-------
|
||||
|
||||
When making the switch you first need to learn some about the new data structure for images:
|
||||
@ref tutorial_mat_the_basic_image_container, 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:
|
||||
@code{.cpp}
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
@endcode
|
||||
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{.cpp}
|
||||
using namespace cv; // The new C++ interface API is inside this namespace. Import it.
|
||||
@endcode
|
||||
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 tutorial_windows_visual_studio_opencv and for
|
||||
Linux an example usage is explained in @ref tutorial_linux_eclipse.
|
||||
|
||||
Now for converting the *Mat* object you can use either the *IplImage* or the *CvMat* operators.
|
||||
While in the C interface you used to work with pointers here it's no longer the case. In the C++
|
||||
interface we have mostly *Mat* objects. These objects may be freely converted to both *IplImage* and
|
||||
*CvMat* with simple assignment. For example:
|
||||
@code{.cpp}
|
||||
Mat I;
|
||||
IplImage pI = I;
|
||||
CvMat mI = I;
|
||||
@endcode
|
||||
Now if you want pointers the conversion gets just a little more complicated. The compilers can no
|
||||
longer automatically determinate what you want and as you need to explicitly specify your goal. This
|
||||
is to call the *IplImage* and *CvMat* operators and then get their pointers. For getting the pointer
|
||||
we use the & sign:
|
||||
@code{.cpp}
|
||||
Mat I;
|
||||
IplImage* pI = &I.operator IplImage();
|
||||
CvMat* mI = &I.operator CvMat();
|
||||
@endcode
|
||||
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 leaks. 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* :
|
||||
@code{.cpp}
|
||||
Ptr<IplImage> piI = &I.operator IplImage();
|
||||
@endcode
|
||||
Converting from the C data structures to the *Mat* is done by passing these inside its constructor.
|
||||
For example:
|
||||
@code{.cpp}
|
||||
Mat K(piL), L;
|
||||
L = Mat(pI);
|
||||
@endcode
|
||||
|
||||
A case study
|
||||
------------
|
||||
|
||||
Now that you have the basics done [here's](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp)
|
||||
an example that mixes the usage of the C interface with the C++ one. You will also find it in the
|
||||
sample directory of the OpenCV source code library at the
|
||||
`samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp` .
|
||||
To further help on seeing the difference the programs supports two modes: one mixed C and C++ and
|
||||
one pure C++. If you define the *DEMO_MIXED_API_USE* you'll end up using the first. The program
|
||||
separates the color planes, does some modifications on them and in the end merge them back together.
|
||||
|
||||
@snippet interoperability_with_OpenCV_1.cpp head
|
||||
@snippet interoperability_with_OpenCV_1.cpp start
|
||||
|
||||
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.
|
||||
|
||||
@snippet interoperability_with_OpenCV_1.cpp new
|
||||
|
||||
Because, we want to mess around with the images luma component we first convert from the default BGR
|
||||
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:
|
||||
|
||||
@snippet interoperability_with_OpenCV_1.cpp scanning
|
||||
|
||||
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 tutorial_how_to_scan_images 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:
|
||||
|
||||
@snippet interoperability_with_OpenCV_1.cpp noisy
|
||||
|
||||
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.
|
||||
|
||||
@snippet interoperability_with_OpenCV_1.cpp end
|
||||
|
||||
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:
|
||||
|
||||
![](images/outputInteropOpenCV1.jpg)
|
||||
|
||||
You may observe a runtime instance of this on the [YouTube
|
||||
here](https://www.youtube.com/watch?v=qckm-zvo31w) and you can [download the source code from here
|
||||
](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp)
|
||||
or find it in the
|
||||
`samples/cpp/tutorial_code/core/interoperability_with_OpenCV_1/interoperability_with_OpenCV_1.cpp`
|
||||
of the OpenCV source code library.
|
||||
|
||||
@youtube{qckm-zvo31w}
|
@ -150,11 +150,12 @@ If we need to copy the data, this is done using, for example, cv::Mat::copyTo or
|
||||
@snippet samples/python/tutorial_code/core/mat_operations/mat_operations.py Reference counting 2
|
||||
@end_toggle
|
||||
|
||||
To the contrary with C API where an output image had to be created by the developer, an empty output Mat
|
||||
can be supplied to each function. Each implementation calls Mat::create for a destination matrix.
|
||||
This method allocates data for a matrix if it is empty. If it is not empty and has the correct size
|
||||
and type, the method does nothing. If however, size or type are different from the input arguments, the
|
||||
data is deallocated (and lost) and a new data is allocated. For example:
|
||||
An empty output Mat can be supplied to each function.
|
||||
Each implementation calls Mat::create for a destination matrix.
|
||||
This method allocates data for a matrix if it is empty.
|
||||
If it is not empty and has the correct size and type, the method does nothing.
|
||||
If however, size or type are different from the input arguments, the data is deallocated (and lost) and a new data is allocated.
|
||||
For example:
|
||||
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/core/mat_operations/mat_operations.cpp Reference counting 3
|
||||
@ -199,12 +200,6 @@ Selecting a region of interest:
|
||||
@snippet samples/python/tutorial_code/core/mat_operations/mat_operations.py Select ROI
|
||||
@end_toggle
|
||||
|
||||
A conversion from Mat to C API data structures (**C++ only**):
|
||||
|
||||
@snippet samples/cpp/tutorial_code/core/mat_operations/mat_operations.cpp C-API conversion
|
||||
|
||||
Note that there is no data copying here.
|
||||
|
||||
Conversion from color to greyscale:
|
||||
|
||||
@add_toggle_cpp
|
||||
|
@ -82,17 +82,6 @@ understanding how to manipulate the images on a pixel level.
|
||||
You will see how to use the @ref cv::FileStorage data structure of OpenCV to write and read
|
||||
data to XML or YAML file format.
|
||||
|
||||
- @subpage tutorial_interoperability_with_OpenCV_1
|
||||
|
||||
*Compatibility:* \> OpenCV 2.0
|
||||
|
||||
*Author:* Bernát Gábor
|
||||
|
||||
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.
|
||||
|
||||
|
||||
- @subpage tutorial_how_to_use_OpenCV_parallel_for_
|
||||
|
||||
*Compatibility:* \>= OpenCV 2.4.3
|
||||
|
@ -62,8 +62,6 @@ Changes intended to ease the migration have been made in OpenCV 3.0, thus the fo
|
||||
#include "opencv2/<module>.hpp"
|
||||
@endcode
|
||||
|
||||
2. If your code is using C API (`cv*` functions, `Cv*` structures or `CV_*` enumerations), include corresponding `*_c.h` headers. Although it is recommended to use C++ API, most of C-functions are still accessible in separate header files (opencv2/core/core_c.h, opencv2/core/types_c.h, opencv2/imgproc/imgproc_c.h, etc.).
|
||||
|
||||
Modern way to use algorithm {#tutorial_transition_algorithm}
|
||||
---------------------------
|
||||
1. Algorithm instances must be created with cv::makePtr function or corresponding static factory method if available:
|
||||
|
@ -614,12 +614,11 @@ Note that `M.step[i] >= M.step[i+1]` (in fact, `M.step[i] >= M.step[i+1]*M.size[
|
||||
that 2-dimensional matrices are stored row-by-row, 3-dimensional matrices are stored plane-by-plane,
|
||||
and so on. M.step[M.dims-1] is minimal and always equal to the element size M.elemSize() .
|
||||
|
||||
So, the data layout in Mat is fully compatible with CvMat, IplImage, and CvMatND types from OpenCV
|
||||
1.x. It is also compatible with the majority of dense array types from the standard toolkits and
|
||||
SDKs, such as Numpy (ndarray), Win32 (independent device bitmaps), and others, that is, with any
|
||||
array that uses *steps* (or *strides*) to compute the position of a pixel. Due to this
|
||||
compatibility, it is possible to make a Mat header for user-allocated data and process it in-place
|
||||
using OpenCV functions.
|
||||
So, the data layout in Mat is compatible with the majority of dense array types from the standard
|
||||
toolkits and SDKs, such as Numpy (ndarray), Win32 (independent device bitmaps), and others,
|
||||
that is, with any array that uses *steps* (or *strides*) to compute the position of a pixel.
|
||||
Due to this compatibility, it is possible to make a Mat header for user-allocated data and process
|
||||
it in-place using OpenCV functions.
|
||||
|
||||
There are many different ways to create a Mat object. The most popular options are listed below:
|
||||
|
||||
@ -704,10 +703,6 @@ sub-matrices.
|
||||
Mat M = Mat(3, 3, CV_64F, m).inv();
|
||||
@endcode
|
||||
.
|
||||
Partial yet very common cases of this *user-allocated data* case are conversions from CvMat and
|
||||
IplImage to Mat. For this purpose, there is function cv::cvarrToMat taking pointers to CvMat or
|
||||
IplImage and the optional flag indicating whether to copy the data or not.
|
||||
@snippet samples/cpp/image.cpp iplimage
|
||||
|
||||
- Use MATLAB-style array initializers, zeros(), ones(), eye(), for example:
|
||||
@code
|
||||
@ -1641,13 +1636,6 @@ public:
|
||||
*/
|
||||
Mat operator()(const std::vector<Range>& ranges) const;
|
||||
|
||||
// //! converts header to CvMat; no data is copied
|
||||
// operator CvMat() const;
|
||||
// //! converts header to CvMatND; no data is copied
|
||||
// operator CvMatND() const;
|
||||
// //! converts header to IplImage; no data is copied
|
||||
// operator IplImage() const;
|
||||
|
||||
template<typename _Tp> operator std::vector<_Tp>() const;
|
||||
template<typename _Tp, int n> operator Vec<_Tp, n>() const;
|
||||
template<typename _Tp, int m, int n> operator Matx<_Tp, m, n>() const;
|
||||
|
@ -1,135 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/core/utility.hpp>
|
||||
|
||||
using namespace cv; // all the new API is put into "cv" namespace. Export its content
|
||||
using namespace std;
|
||||
|
||||
static void help()
|
||||
{
|
||||
cout <<
|
||||
"\nThis program shows how to use cv::Mat and IplImages converting back and forth.\n"
|
||||
"It shows reading of images, converting to planes and merging back, color conversion\n"
|
||||
"and also iterating through pixels.\n"
|
||||
"Call:\n"
|
||||
"./image [image-name Default: ../data/lena.jpg]\n" << endl;
|
||||
}
|
||||
|
||||
// enable/disable use of mixed API in the code below.
|
||||
#define DEMO_MIXED_API_USE 1
|
||||
|
||||
#ifdef DEMO_MIXED_API_USE
|
||||
# include <opencv2/highgui/highgui_c.h>
|
||||
# include <opencv2/imgcodecs/imgcodecs_c.h>
|
||||
#endif
|
||||
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
cv::CommandLineParser parser(argc, argv, "{help h | |}{@image|../data/lena.jpg|}");
|
||||
if (parser.has("help"))
|
||||
{
|
||||
help();
|
||||
return 0;
|
||||
}
|
||||
string imagename = parser.get<string>("@image");
|
||||
#if DEMO_MIXED_API_USE
|
||||
//! [iplimage]
|
||||
Ptr<IplImage> iplimg(cvLoadImage(imagename.c_str())); // Ptr<T> is safe ref-counting pointer class
|
||||
if(!iplimg)
|
||||
{
|
||||
fprintf(stderr, "Can not load image %s\n", imagename.c_str());
|
||||
return -1;
|
||||
}
|
||||
Mat img = cv::cvarrToMat(iplimg); // cv::Mat replaces the CvMat and IplImage, but it's easy to convert
|
||||
// between the old and the new data structures (by default, only the header
|
||||
// is converted, while the data is shared)
|
||||
//! [iplimage]
|
||||
#else
|
||||
Mat img = imread(imagename); // the newer cvLoadImage alternative, MATLAB-style function
|
||||
if(img.empty())
|
||||
{
|
||||
fprintf(stderr, "Can not load image %s\n", imagename.c_str());
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( img.empty() ) // check if the image has been loaded properly
|
||||
return -1;
|
||||
|
||||
Mat img_yuv;
|
||||
cvtColor(img, img_yuv, COLOR_BGR2YCrCb); // convert image to YUV color space. The output image will be created automatically
|
||||
|
||||
vector<Mat> planes; // Vector is template vector class, similar to STL's vector. It can store matrices too.
|
||||
split(img_yuv, planes); // split the image into separate color planes
|
||||
|
||||
#if 1
|
||||
// method 1. process Y plane using an iterator
|
||||
MatIterator_<uchar> it = planes[0].begin<uchar>(), it_end = planes[0].end<uchar>();
|
||||
for(; it != it_end; ++it)
|
||||
{
|
||||
double v = *it*1.7 + rand()%21-10;
|
||||
*it = saturate_cast<uchar>(v*v/255.);
|
||||
}
|
||||
|
||||
// method 2. process the first chroma plane using pre-stored row pointer.
|
||||
// method 3. process the second chroma plane using individual element access
|
||||
for( int y = 0; y < img_yuv.rows; y++ )
|
||||
{
|
||||
uchar* Uptr = planes[1].ptr<uchar>(y);
|
||||
for( int x = 0; x < img_yuv.cols; x++ )
|
||||
{
|
||||
Uptr[x] = saturate_cast<uchar>((Uptr[x]-128)/2 + 128);
|
||||
uchar& Vxy = planes[2].at<uchar>(y, x);
|
||||
Vxy = saturate_cast<uchar>((Vxy-128)/2 + 128);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
Mat noise(img.size(), CV_8U); // another Mat constructor; allocates a matrix of the specified size and type
|
||||
randn(noise, Scalar::all(128), Scalar::all(20)); // fills the matrix with normally distributed random values;
|
||||
// there is also randu() for uniformly distributed random number generation
|
||||
GaussianBlur(noise, noise, Size(3, 3), 0.5, 0.5); // blur the noise a bit, kernel size is 3x3 and both sigma's are set to 0.5
|
||||
|
||||
const double brightness_gain = 0;
|
||||
const double contrast_gain = 1.7;
|
||||
#if DEMO_MIXED_API_USE
|
||||
// it's easy to pass the new matrices to the functions that only work with IplImage or CvMat:
|
||||
// step 1) - convert the headers, data will not be copied
|
||||
IplImage cv_planes_0 = planes[0], cv_noise = noise;
|
||||
// step 2) call the function; do not forget unary "&" to form pointers
|
||||
cvAddWeighted(&cv_planes_0, contrast_gain, &cv_noise, 1, -128 + brightness_gain, &cv_planes_0);
|
||||
#else
|
||||
addWeighted(planes[0], contrast_gain, noise, 1, -128 + brightness_gain, planes[0]);
|
||||
#endif
|
||||
const double color_scale = 0.5;
|
||||
// Mat::convertTo() replaces cvConvertScale. One must explicitly specify the output matrix type (we keep it intact - planes[1].type())
|
||||
planes[1].convertTo(planes[1], planes[1].type(), color_scale, 128*(1-color_scale));
|
||||
// alternative form of cv::convertScale if we know the datatype at compile time ("uchar" here).
|
||||
// This expression will not create any temporary arrays and should be almost as fast as the above variant
|
||||
planes[2] = Mat_<uchar>(planes[2]*color_scale + 128*(1-color_scale));
|
||||
|
||||
// Mat::mul replaces cvMul(). Again, no temporary arrays are created in case of simple expressions.
|
||||
planes[0] = planes[0].mul(planes[0], 1./255);
|
||||
#endif
|
||||
|
||||
// now merge the results back
|
||||
merge(planes, img_yuv);
|
||||
// and produce the output RGB image
|
||||
cvtColor(img_yuv, img, COLOR_YCrCb2BGR);
|
||||
|
||||
// this is counterpart for cvNamedWindow
|
||||
namedWindow("image with grain", WINDOW_AUTOSIZE);
|
||||
#if DEMO_MIXED_API_USE
|
||||
// this is to demonstrate that img and iplimg really share the data - the result of the above
|
||||
// processing is stored in img and thus in iplimg too.
|
||||
cvShowImage("image with grain", iplimg);
|
||||
#else
|
||||
imshow("image with grain", img);
|
||||
#endif
|
||||
waitKey();
|
||||
|
||||
return 0;
|
||||
// all the memory will automatically be released by Vector<>, Mat and Ptr<> destructors.
|
||||
}
|
@ -1,149 +0,0 @@
|
||||
//! [head]
|
||||
#include <iostream>
|
||||
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include "opencv2/imgcodecs.hpp"
|
||||
#include <opencv2/highgui.hpp>
|
||||
|
||||
using namespace cv; // The new C++ interface API is inside this namespace. Import it.
|
||||
using namespace std;
|
||||
//! [head]
|
||||
|
||||
static void help( char* progName)
|
||||
{
|
||||
cout << endl << progName
|
||||
<< " shows how to use cv::Mat and IplImages together (converting back and forth)." << endl
|
||||
<< "Also contains example for image read, splitting the planes, merging back and " << endl
|
||||
<< " color conversion, plus iterating through pixels. " << endl
|
||||
<< "Usage:" << endl
|
||||
<< progName << " [image-name Default: ../data/lena.jpg]" << endl << endl;
|
||||
}
|
||||
|
||||
//! [start]
|
||||
// comment out the define to use only the latest C++ API
|
||||
#define DEMO_MIXED_API_USE
|
||||
|
||||
#ifdef DEMO_MIXED_API_USE
|
||||
# include <opencv2/highgui/highgui_c.h>
|
||||
# include <opencv2/imgcodecs/imgcodecs_c.h>
|
||||
#endif
|
||||
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
help(argv[0]);
|
||||
const char* imagename = argc > 1 ? argv[1] : "../data/lena.jpg";
|
||||
|
||||
#ifdef DEMO_MIXED_API_USE
|
||||
Ptr<IplImage> IplI(cvLoadImage(imagename)); // Ptr<T> is a safe ref-counting pointer class
|
||||
if(!IplI)
|
||||
{
|
||||
cerr << "Can not load image " << imagename << endl;
|
||||
return -1;
|
||||
}
|
||||
Mat I = cv::cvarrToMat(IplI); // Convert to the new style container. Only header created. Image not copied.
|
||||
#else
|
||||
Mat I = imread(imagename); // the newer cvLoadImage alternative, MATLAB-style function
|
||||
if( I.empty() ) // same as if( !I.data )
|
||||
{
|
||||
cerr << "Can not load image " << imagename << endl;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
//! [start]
|
||||
|
||||
//! [new]
|
||||
// convert image to YUV color space. The output image will be created automatically.
|
||||
Mat I_YUV;
|
||||
cvtColor(I, I_YUV, COLOR_BGR2YCrCb);
|
||||
|
||||
vector<Mat> planes; // Use the STL's vector structure to store multiple Mat objects
|
||||
split(I_YUV, planes); // split the image into separate color planes (Y U V)
|
||||
//! [new]
|
||||
|
||||
#if 1 // change it to 0 if you want to see a blurred and noisy version of this processing
|
||||
//! [scanning]
|
||||
// Mat scanning
|
||||
// Method 1. process Y plane using an iterator
|
||||
MatIterator_<uchar> it = planes[0].begin<uchar>(), it_end = planes[0].end<uchar>();
|
||||
for(; it != it_end; ++it)
|
||||
{
|
||||
double v = *it * 1.7 + rand()%21 - 10;
|
||||
*it = saturate_cast<uchar>(v*v/255);
|
||||
}
|
||||
|
||||
for( int y = 0; y < I_YUV.rows; y++ )
|
||||
{
|
||||
// Method 2. process the first chroma plane using pre-stored row pointer.
|
||||
uchar* Uptr = planes[1].ptr<uchar>(y);
|
||||
for( int x = 0; x < I_YUV.cols; x++ )
|
||||
{
|
||||
Uptr[x] = saturate_cast<uchar>((Uptr[x]-128)/2 + 128);
|
||||
|
||||
// Method 3. process the second chroma plane using individual element access
|
||||
uchar& Vxy = planes[2].at<uchar>(y, x);
|
||||
Vxy = saturate_cast<uchar>((Vxy-128)/2 + 128);
|
||||
}
|
||||
}
|
||||
//! [scanning]
|
||||
|
||||
#else
|
||||
|
||||
//! [noisy]
|
||||
Mat noisyI(I.size(), CV_8U); // Create a matrix of the specified size and type
|
||||
|
||||
// Fills the matrix with normally distributed random values (around number with deviation off).
|
||||
// There is also randu() for uniformly distributed random number generation
|
||||
randn(noisyI, Scalar::all(128), Scalar::all(20));
|
||||
|
||||
// blur the noisyI a bit, kernel size is 3x3 and both sigma's are set to 0.5
|
||||
GaussianBlur(noisyI, noisyI, Size(3, 3), 0.5, 0.5);
|
||||
|
||||
const double brightness_gain = 0;
|
||||
const double contrast_gain = 1.7;
|
||||
|
||||
#ifdef DEMO_MIXED_API_USE
|
||||
// To pass the new matrices to the functions that only work with IplImage or CvMat do:
|
||||
// step 1) Convert the headers (tip: data will not be copied).
|
||||
// step 2) call the function (tip: to pass a pointer do not forget unary "&" to form pointers)
|
||||
|
||||
IplImage cv_planes_0 = planes[0], cv_noise = noisyI;
|
||||
cvAddWeighted(&cv_planes_0, contrast_gain, &cv_noise, 1, -128 + brightness_gain, &cv_planes_0);
|
||||
#else
|
||||
addWeighted(planes[0], contrast_gain, noisyI, 1, -128 + brightness_gain, planes[0]);
|
||||
#endif
|
||||
|
||||
const double color_scale = 0.5;
|
||||
// Mat::convertTo() replaces cvConvertScale.
|
||||
// One must explicitly specify the output matrix type (we keep it intact - planes[1].type())
|
||||
planes[1].convertTo(planes[1], planes[1].type(), color_scale, 128*(1-color_scale));
|
||||
|
||||
// alternative form of cv::convertScale if we know the datatype at compile time ("uchar" here).
|
||||
// This expression will not create any temporary arrays ( so should be almost as fast as above)
|
||||
planes[2] = Mat_<uchar>(planes[2]*color_scale + 128*(1-color_scale));
|
||||
|
||||
// Mat::mul replaces cvMul(). Again, no temporary arrays are created in case of simple expressions.
|
||||
planes[0] = planes[0].mul(planes[0], 1./255);
|
||||
//! [noisy]
|
||||
#endif
|
||||
|
||||
|
||||
//! [end]
|
||||
merge(planes, I_YUV); // now merge the results back
|
||||
cvtColor(I_YUV, I, COLOR_YCrCb2BGR); // and produce the output RGB image
|
||||
|
||||
namedWindow("image with grain", WINDOW_AUTOSIZE); // use this to create images
|
||||
|
||||
#ifdef DEMO_MIXED_API_USE
|
||||
// this is to demonstrate that I and IplI really share the data - the result of the above
|
||||
// processing is stored in I and thus in IplI too.
|
||||
cvShowImage("image with grain", IplI);
|
||||
#else
|
||||
imshow("image with grain", I); // the new MATLAB style function show
|
||||
#endif
|
||||
//! [end]
|
||||
waitKey();
|
||||
|
||||
// Tip: No memory freeing is required!
|
||||
// All the memory will be automatically released by the Vector<>, Mat and Ptr<> destructor.
|
||||
return 0;
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
/* Snippet code for Operations with images tutorial (not intended to be run but should built successfully) */
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/core/core_c.h"
|
||||
#include "opencv2/imgcodecs.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
@ -128,15 +127,6 @@ int main(int,char**)
|
||||
CV_UNUSED(smallImg);
|
||||
}
|
||||
}
|
||||
{
|
||||
//! [C-API conversion]
|
||||
Mat img = imread("image.jpg");
|
||||
IplImage img1 = img;
|
||||
CvMat m = img;
|
||||
//! [C-API conversion]
|
||||
CV_UNUSED(img1);
|
||||
CV_UNUSED(m);
|
||||
}
|
||||
{
|
||||
//! [BGR to Gray]
|
||||
Mat img = imread("image.jpg"); // loading a 8UC3 image
|
||||
|
Loading…
Reference in New Issue
Block a user