Converting a Matrix to a Vector in openCV - opencv

I have an image 16x16 pixel image , how can I put it in a matrix 1x256 pixel and then convert it back to a 16x16 pixel Using opencv ?
I tried reshape but it didn't succeed as when i make cout<< image.cols << image.rows give me the same number which is 16,16 also sometimes the image is not continuous so reshape won't work
Btw I need it in coding a neural network classifier.

// create matrix for the result
Mat image1x256(Size(256,1), image.type());
// use reshape function
Mat image16x16 = image1x256.reshape(image.channels(), 16);
// copy the data from your image to new image
image.copyTo(image16x16);
Since image16x16 and image1x256 are just different pointers to same data, then copying the data to one of them will actually change both.
Note that reshape function creates a new header (i.e. new smart pointer) that may be used instead of old one, but it is not changing properties of the original header that still exist and can be used.

Related

copy multiple 1D matrix into one large 1D matrix in Emgucv or Opencv

I was trying to create a large Matrix contain rows images of tablets to use PCA function in Emgucv.
I was success in reshaping the tablet image (let say MxN) to a matrix ( 1 row,MxN column).Now I want to copy it to row i of the large Matrix ( k row, MxN column).Here is my code:
Matrix<byte> largeMatrix= new Matrix<byte> (k,M*N);
Matrix<byte> temp = new Matrix<byte>(M,N); //tablet image
Matrix<byte> temp1 = new Matrix<byte>(1,M*N); //tablet image after reshaping into 1 row
CvInvoke.cvConvert(src.Copy(),temp);
CvInvoke.cvReshape(temp, temp1, 0, 1);
//Written in C# using Emgucv
How to copy temp1 into exactly row i of matrix largeMatrix in Emgucv ( or Opencv ).
This is pretty easy. I'm sorry I only have C++ code for you though.
cv::Mat dest; // size NxM (rowsxcols)
cv::Mat src; // size N
cv::Mat row(dest.row(i));
src.copyTo(row);
Now what is happening here?
The Mat row is a matrix header that wraps exactly the row i of dest. It does not create a copy but simply gives a different view of the same data. Then, the copyTo() method actually copies the data between two matrices.
It is important here to not write row = src. That would only change the header of row, not the data it points to.

Thin line removal in binary images using OpenCV

I'm currently using OpenCV for detecting blobs in a binary image. I'd like to erase small lines without changing the big objects.
Here's an example: The original image is
And I want to convert it into the following
"Opening" didn't work, because when applying it the edges of the triangle were cut off. Is there any other method for removing the lines, without losing information of the big triangle?
Use Erosion to remove such a noise,
The code look like,
Mat src;//load source
Mat dst;//destination image
Mat element = getStructuringElement( MORPH_RECT,Size(5,5), Point( -1, -1 ) ); // kernel performing drode
erode( src, dst, element );
Edit
Adding #Bull comments here as it more appropriate method, which suggest erosion followed by dilation will get you very close to what you want.

Converting matches from 8-bit 4 channels to 64-bit 1 channel in OpenCV

I have a vector of Point2f which have color space CV_8UC4 and need to convert them to CV_64F, is the following code correct?
points1.convertTo(points1, CV_64F);
More details:
I am trying to use this function to calculate the essential matrix (rotation/translation) through the 5-point algorithm, instead of using the findFundamentalMath included in OpenCV, which is based on the 8-point algorithm:
https://github.com/prclibo/relative-pose-estimation/blob/master/five-point-nister/five-point.cpp#L69
As you can see it first converts the image to CV_64F. My input image is a CV_8UC4, BGRA image. When I tested the function, both BGRA and greyscale images produce valid matrices from the mathematical point of view, but if I pass a greyscale image instead of color, it takes way more to calculate. Which makes me think I'm not doing something correctly in one of the two cases.
I read around that when the change in color space is not linear (which I suppose is the case when you go from 4 channels to 1 like in this case), you should normalize the intensity value. Is that correct? Which input should I give to this function?
Another note, the function is called like this in my code:
vector<Point2f>imgpts1, imgpts2;
for (vector<DMatch>::const_iterator it = matches.begin(); it!= matches.end(); ++it)
{
imgpts1.push_back(firstViewFeatures.second[it->queryIdx].pt);
imgpts2.push_back(secondViewFeatures.second[it->trainIdx].pt);
}
Mat mask;
Mat E = findEssentialMat(imgpts1, imgpts2, [camera focal], [camera principal_point], CV_RANSAC, 0.999, 1, mask);
The fact I'm not passing a Mat, but a vector of Point2f instead, seems to create no problems, as it compiles and executes properly.
Is it the case I should store the matches in a Mat?
I am no sure do you mean by vector of Point2f in some color space, but if you want to convert vector of points into vector of points of another type you can use any standard C++/STL function like copy(), assign() or insert(). For example:
copy(floatPoints.begin(), floatPoints.end(), doublePoints.begin());
or
doublePoints.insert(doublePoints.end(), floatPoints.begin(), floatPoints.end());
No, it is not. A std::vector<cv::Pointf2f> cannot make use of the OpenCV convertTo function.
I think you really mean that you have a cv::Mat points1 of type CV_8UC4. Note that those are RxCx4 values (being R and C the number of rows and columns), and that in a CV_64F matrix you will have RxC values only. So, you need to be more clear on how you want to transform those values.
You can do points1.convertTo(points1, CV_64FC4) to get a RxCx4 matrix.
Update:
Some remarks after you updated the question:
Note that a vector<cv::Point2f> is a vector of 2D points that is not associated to any particular color space, they are just coordinates in the image axes. So, they represent the same 2D points in a grey, rgb or hsv image. Then, the execution time of findEssentialMat doesn't depend on the image color space. Getting the points may, though.
That said, I think your input for findEssentialMat is ok (the function takes care of the vectors and convert them into their internal representation). In this cases, it is very useful to draw the points in your image to debug the code.

Finding Local Maxima in an Image

I want to find local maxima of each '3X3' sized Window. So, How do we find that local maxima of each 3X3 sized Window in an image in OpenCV ?
You can use morphological operation dilate:
Mat img; // your input image that you should fill with values
Mat maxims(img.size(), img.type()); // container for all local maximums
dilate(img, maxims, Mat());
As a result each pixel of 'maxims' is maximum of appropriate 3x3 window in 'img'. Read more about morphological operation (dilatation, erosion, close, open, etc...) on Wikipedia or somewhere else.
Please see my answer to Find local maxima in grayscale image using OpenCV
The idea is to dilate with a kernel that has a "hole" in the middle (i.e. replace each pixel with the maximum of all its neighbors, excluding the pixel itself), and then compare the result to the original image.

Opencv Transforming Image

I am new to Open Cv, I want to transform the two images src and dst image . I am using cv::estimateRigidTransform() to calculate the transformation matrix and after that using cv::warpAffine() to transform from dst to src. when I compare the new transformed image with src image it is almost same (transformed), but when I am getting the abs difference of new transformed image and the src image, there is lot of difference. what should I do as My dst image has some rotation and translation factor as well. here is my code
cv::Mat transformMat = cv::estimateRigidTransform(src, dst, true);
cv::Mat output;
cv::Size dsize = leftImageMat.size(); //This specifies the output image size--change needed
cv::warpAffine(src, output, transformMat, dsize);
Src Image
destination Image
output image
absolute Difference Image
Thanks
You have some misconceptions about the process.
The method cv::estimateRigidTransform takes as input two sets of corresponding points. And then solves set of equations to find the transformation matrix. The output of the transformation matches src points to dst points (exactly or closely, if exact match is not possible - for example float coordinates).
If you apply estimateRigidTransform on two images, OpenCV first find matching pairs of points using some internal method (see opencv docs).
cv::warpAffine then transforms the src image to dst according to given transformation matrix. But any (almost any) transformation is loss operation. The algorithm has to estimate some data, because they aren't available. This process is called interpolation, using known information you calculate the unknown value. Some info regarding image scaling can be found on wiki. Same rules apply to other transformations - rotation, skew, perspective... Obviously this doesn't apply to translation.
Given your test images, I would guess that OpenCV takes the lampshade as reference. From the difference is clear that the lampshade is transformed best. Default the OpenCV uses linear interpolation for warping as it's fastest method. But you can set more advances method for better results - again consult opencv docs.
Conclusion:
The result you got is pretty good, if you bear in mind, it's result of automated process. If you want better results, you'll have to find another method for selecting corresponding points. Or use better interpolation method. Either way, after the transform, the diff will not be 0. It virtually impossible to achieve that, because bitmap is discrete grid of pixels, so there will always be some gaps, which needs to be estimated.

Resources