I am converting Python OpenCV code to Emgu.
In Python, function findContours can return hierarchy
hierarchy – Optional output vector, containing information about the image topology. It has as many elements as the number of contours. For each i-th contour contours[i] , the elements hierarchy[i][0] , hiearchy[i][1] , hiearchy[i][2] , and hiearchy[i][3] are set to 0-based indices in contours of the next and previous contours at the same hierarchical level, the first child contour and the parent contour, respectively. If for the contour i there are no next, previous, parent, or nested contours, the corresponding elements of hierarchy[i] will be negative.
Unfortunately in Emgu I can't not return such array for findContours function.Is there any equivalent for this?
If you choose CV_RETR_TREE as retrieval type, the Contour<Point> that is returned will contain a hierarchical tree structure.
This image from here shows how you can navigate in the hierarchy using h_next and v_next pointers in OpenCV (i.e. HNext and VNext in Emgu CV).
In this way, you can get the whole hierarchy.
Related
Given a binary image with multiple objects in it, I would like to enclose each object in contour. And then, I would like to calculate area inside object, followed by area inside contour. Any ideas how to do this?
Use the OpenCV findContours() method for contours, the contourArea() method for contour area, and the OpenCV Moments class to calculate the object area.
See these pages from the OpenCV documentation site:
Contours
Contour Features
I am using Image processing, openCV , C++ to check the misshapes of bottles. I am very new to openCV. It will be a great help if someone can guide me a right direction how to achieve this. How can I detect the defects of the shape of the bottle using opencv and c++. I am giving bottle images as the inputs to the system.when a misshaped bottle is input system should detect it.
Defected bottle image :
Good Bottle image :
Basic approach:
you can extract the edges then Register the two images. In openCV you will get couple of filters for this.
Perfect Approach:
you can use statistical shape modeling algorithm, I am not sure if it is there in OPenCV.
Take the region of interest (ROI) and find contours.
Find convexhull
Find convexity defects
Do this for both the reference ROI and the defected ROI, then compare
The comparison would not be straightforward as you may have to establish some correspondence between the regions of the two contours(may be you can use a grid and use its cells as the ROIs - now many ROIs for a single image - to solve the correspondence complexities)
ROI in red:
Grid based approach (multiple ROIs):
You could try the opencv template matching function. From the opencv documentation:
Template matching is a technique for finding areas of an image that match (are similar) to a template image (patch).
It implements a sliding window scheme, by sliding the template image that we want to find over the source image and calculating a similarity metric that is stored in a result matrix.
In the result matrix, the darkest/brightest location indicates the highest matches (according to the template matching algorithm employed), which marks the position of the best match for the template. The brightest location can be found using the minMaxLoc function on the result matrix.
The signature of the matchTemplate method is as follows:
matchTemplate( image, template, result, match_method ); //Matches the template
normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() ); //Normalizes the result
double minVal; double maxVal; Point minLoc; Point maxLoc; Point matchLoc;
minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() ); //Finds the minimum and maximum values in the result
OpenCV provides several different algorithms for the matching, such as finding the normalized square difference of intensities(CV_TM_SQDIFF_NORMED). For the result matrix obtained using CV_TM_SQDIFF_NORMED, the lowest values correspond to the best matches. For other methods such as normalized cross correlation (CV_TM_CCORR_NORMED), the highest values correspond to the best matches.
In your case, you could threshold the result matrix with a tolerance value for deviation from the template image, and if the result on thresholding is an empty Mat, you could identify the bottle to be defective. You might have to experiment a little to find an appropriate threshold. If you want an exact match, you have to look for 0/1 (according to method) in the result matrix.
You can find more on opencv template matching here.
Hope this helps.
New to OpenCV here. I'm trying to understand what a hierarchy vector is supposed to contain. I understand that for object tracking and when using the findCountours function, it is common to use vector, but I would like to understand what this means. Thanks in advance for the help!
A contour is a closed edge around an area of an image. This contour could contain contours so we need a way to store this hierarchy. The hierarchy vector contains all of the information to explain how contours are nested in each other.
From the OpenCV documentation it is a
Optional output vector, containing information about the image topology. It has as many elements as the number of contours. For each i-th contour contours[i] , the elements hierarchy[i][0] , hiearchy[i][1] , hiearchy[i][2] , and hiearchy[i][3] are set to 0-based indices in contours of the next and previous contours at the same hierarchical level, the first child contour and the parent contour, respectively. If for the contour i there are no next, previous, parent, or nested contours, the corresponding elements of hierarchy[i] will be negative.
You can think of this as a doubly linked list, but each item in the list points could possibly point to a parent and/or child. We can use the next and previous indices to find all of the contours that have the same parent. Each contour will point to a child linked list if they contain a child contour. A negative value is the same as a NULL pointer for a traditional linked list.
An example:
a
|
b,c,d,e,f
| |
g h,i
a points to b as one child and from b we know that b, c, d, e, and f are all contained at the same level in a. b also has a child contour g. e has two children as well.
In the Computer Vision System Toolbox for Matlab there are three types of interpolation methods used for Correct lens distortion.
Interpolation method for the function to use on the input image. The interp input interpolation method can be the string, 'nearest', 'linear', or 'cubic'.
My question is: what is the difference between 'nearest', 'linear', or 'cubic' ? and which one implemented in "Zhang" and "Heikkila, J, and O. Silven" methods.
I can't access the paged at the link you wrote in your question (it asks for a username and password) and so I assume your linked page has the same contents of the page http://www.mathworks.it/it/help/vision/ref/undistortimage.html which I quote here:
J = undistortImage(I,cameraParameters,interp) removes lens distortion from the input image, I and specifies the
interpolation method for the function to use on the input image.
Input Arguments
I — Input image
cameraParameters — Object for storing camera parameters
interp — Interpolation method
'linear' (default) | 'nearest' | 'cubic'
Interpolation method for the function to use on
the input image. The interp input interpolation method can be the
string, 'nearest', 'linear', or 'cubic'.
Furthermore, I assume you are referring to these papers:
ZHANG, Zhengyou. A flexible new technique for camera calibration. Pattern Analysis and Machine Intelligence, IEEE Transactions on, 2000, 22.11: 1330-1334.
HEIKKILA, Janne; SILVEN, Olli. A four-step camera calibration procedure with implicit image correction. In: Computer Vision and Pattern Recognition, 1997. Proceedings., 1997 IEEE Computer Society Conference on. IEEE, 1997. p. 1106-1112.
I have searched for the word "interpolation" in the two pdf documents Zhang and Heikkila and Silven and I did not find any direct statement about the interpolation method they have used.
To my knowledge, in general, a camera calibration method is concerned on how to estimate the intrinsic, extrinsic and lens distortion parameters (all these parameters are inside the input argument cameraParameters of Matlab's undistortImage function); the interpolation method is part of a different problem, i.e. the problem of "Geometric Image Transformations".
I quote from the OpenCV's page Geometric Image Transformation (I have slightly modified the original omitting some details and adding some definitions, I assume you are working with grey level image):
The functions in this section perform various geometrical
transformations of 2D images. They do not change the image content but
deform the pixel grid and map this deformed grid to the destination
image. In fact, to avoid sampling artifacts, the mapping is done in
the reverse order, from destination to the source. That is, for each
pixel (x, y) of the destination image, the functions compute
coordinates of the corresponding “donor” pixel in the source image and
copy the pixel value:
dst(x,y) = src(f_x(x,y), f_y(x,y))
where
dst(x,y) is the grey value of the pixel located at row x and column y in the destination image
src(x,y) is the grey value of the pixel located at row x and column y in the source image
f_x is a function that maps the row x and the column y to a new row, it just uses coordinates and not the grey level.
f_y is a function that maps the row x and the column y to a new column, it just uses coordinates and not the grey level.
The actual implementations of the geometrical transformations, from
the most generic remap() and to the simplest and the fastest resize()
, need to solve two main problems with the above formula:
• Extrapolation of non-existing pixels. Similarly to the filtering
functions described in the previous section, for some (x,y) , either
one of f_x(x,y) , or f_y(x,y) , or both of them may fall outside of
the image. In this case, an extrapolation method needs to be used.
OpenCV provides the same selection of extrapolation methods as in the
filtering functions. In addition, it provides the method
BORDER_TRANSPARENT . This means that the corresponding pixels in the
destination image will not be modified at all.
• Interpolation of pixel
values. Usually f_x(x,y) and f_y(x,y) are floating-point numbers. This
means that <f_x, f_y> can be either an affine or
perspective transformation, or radial lens distortion correction, and
so on. So, a pixel value at fractional coordinates needs to be
retrieved. In the simplest case, the coordinates can be just rounded
to the nearest integer coordinates and the corresponding pixel can be
used. This is called a nearest-neighbor interpolation. However, a
better result can be achieved by using more sophisticated
interpolation methods, where a polynomial function is fit into some
neighborhood of the computed pixel (f_x(x,y), f_y(x,y)), and then the
value of the polynomial at (f_x(x,y), f_y(x,y)) is taken as the
interpolated pixel value. In OpenCV, you can choose between several
interpolation methods. See resize() for details.
For a "soft" introduction see also for example Cambridge in colour - DIGITAL IMAGE INTERPOLATION.
So let's say you need the grey level of pixel at x=20.2 y=14.7, since x and y are number with a fractional part different from zero you will need to "invent" (compute) the grey level in some way. In the simplest case ('nearest' interpolation) you just say that the grey level at (20.2,14.7) is the grey level you retrieve at (20,15), it is called "nearest" because 20 is the nearest integer value to 20.2 and 15 is the nearest integer value to 14.7.
In the (bi)'linear' interpolation you will compute the value at (20.2,14.7) with a combination of the grey levels of the four pixels at (20,14), (20,15), (21,14), (21,15); for the details on how to compute the combination see the Wikipedia page which has a numeric example.
The (bi)'cubic' interpolation considers the combination of sixteen pixels in order to compute the value at (20.2,14.7), see the Wikipedia page.
I suggest you to try all the three methods, with the same input image, and see the differences in the output image.
Interpolation method is actually independent of the camera calibration. Any time you apply a geometric transformation to an image, such as rotation, re-sizing, or distortion compensation, the pixels in the new image will correspond to points between the pixels of the old image. So you have to interpolate their values somehow.
'nearest' means you simply use the value of the nearest pixel.
'linear' means you use bi-linear interpolation. The new pixel's value is a weighted sum of the values of the neighboring pixels in the input image, where the weights are proportional to distances.
'cubic' means you use a bi-cubic interpolation, which is more complicated than bi-linear, but may give you a smoother image.
A good description of these interpolation methods is given in the documentation for the interp2 function.
And finally, just to clarify, the undistortImage function is in the Computer Vision System Toolbox.
This is my first question here, thank you for reading it.
I am trying to count the number of inner contours inside a contour.
I found a nice tutorial showing how to use h_next and v_next
http://jmpelletier.com/a-simple-opencv-tutorial/
The problem is I use Mat and not IplImage.
I tried to convert it with:
Mat *oimg;
IplImage img = *oimg;
But I get an error when calling cvFindContours.
I also tried usign findContours which is built to work with Mat,
by going through the hierrarchy but it didnt work.
I'm usign C++ and OpenCV2.0
Thanks allot,
Tamir.
Instead of converting the cv::Mat to an IplImage to use the C API, I suggest directly using the C++ version of cvFindContours(): cv::findContours(). Instead of building a true tree data structure, it is flattened and stored in two vectors:
cv::Mat image = // ...
std::vector<std::vector<cv::Point> > contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(image, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);
Check the C++ API documentation for instructions on how to interpret hierarchy (emphasis mine):
hiararchy – The optional output vector
that will contain information about
the image topology. It will have as
many elements as the number of
contours. For each contour contours[i]
, the elements hierarchy[i][0] ,
hiearchyi , hiearchy[i][2] ,
hiearchy[i][3] will be set to 0-based
indices in contours of the next and
previous contours at the same
hierarchical level, the first child
contour and the parent contour,
respectively. If for some contour i
there is no next, previous, parent or
nested contours, the corresponding
elements of hierarchy[i] will be
negative
Switching between the C and C++ API in the same codebase really hurts readability. I suggest only using the C API if the functionality you need is missing from the C++ API.