This question already has an answer here:
Add a row to a matrix in OpenCV
(1 answer)
Closed 5 years ago.
Can alyone tell me how to append a couple of rows (as a cv::Mat) at the end of an existing cv::Mat? since it is a lot of data, I don't want to go through the rows with a for-loop and add them one-by-one. So here is what I want to do:
cv::Mat existing; //This is a Matrix, say of size 700x16
cv::Mat appendNew; //This is the new Matrix with additional data, say of size 200x16.
existing.push_back(appendNew);
If I try to push back the smaller matrix, I get an error of non-matching sizes:
OpenCV Error: Sizes of input arguments do not match
(Pushed vector length is not equal to matrix row length)
So I guess .push_back() tries to append the whole matrix like a kind of new channel, which won't work because it is much smaller than the existing matrix. Does someone know if the appending of the rows at the end of the existing matrix is possible as a whole, not going through them with a for-loop?
It seems like an easy question to me, nevertheless I was not able to find a simple solution online... So thanks in advance!
Cheers:)
You can use cv::hconcat() to append rows, either on top or bottom of a given matrix as:
import cv2
import numpy as np
box = np.ones((50, 50, 3), dtype=np.uint8)
box[:] = np.array([0, 0, 255])
sample_row = np.ones((1, 50, 3), dtype=np.uint8)
sample_row[:] = np.array([255, 0, 0])
for i in xrange(5):
box = cv2.vconcat([box, sample_row])
===>
For visualization purposes I have created a RGB matrix with red color and tried to append Blue rows to the bottom, You may replace with original data, Just make sure that both the matrices to be concatenated have same number of columns and same data type. I have explicitly defined the dtype while creating matrices.
Related
link to code and files
1.I =imread('one.jpg');
2.I = inresize(I,[20,20]);
3.I=im2double(I);
4.I=mean(I,3);
#This next line
5.a = reshape(I,[],400);
I read an image and resizzed it to 20*20 and then converted it to matrix and then find the grayscale .All this I can do in Python too....but I can't do the 5 th line of code...if I tried ,
reshape (I,1,400)...the image appears rotated...I don't know how to write the 5 the line as above in python
The problem
in the link along with the code theres is a displayData function.I saved the matrix i got using python as mat and loaded it on octave when i called displayData() on the matrix i got a rotated image.thats inclued in the link.And theres no such problem in octave.Thank you for looking into this.
For reshaping an array you can use numpy, and, following your code, you can use reshape. In your case, you are changing the size of I, from (20,20) to (1,400).
A complete example which saves the resulting reshaped array to a mat file, using OpenCV APIs for dealing with images, is:
import numpy as np
import cv2
import scipy.io
I = cv2.imread('one.jpg')
I = cv2.resize(I,(20,20))
I = cv2.normalize(I.astype('float'), None, 0.0, 1.0, cv2.NORM_MINMAX)
I = np.mean(I, axis=2)
a = np.reshape(I, (1,400), order='F')
scipy.io.savemat('a.mat', mdict={'a': a})
Note the second parameter of reshape, which is a tuple containing the new size of the array. Also, notice the third parameter order that allows to rearrange elements in column-major style (Fortran) which is the convention used by octave (see reshape in octave http://www.gnu.org/software/octave/doc/v4.0.1/Rearranging-Matrices.html#XREFreshape). This results in a correct image, non rotated, compared to the one got from octave.
However, given the fact that you want to get from a 2d array a 1d array, you can use, from numpy, ravel if you want to get a view of I (when possible), namely a modification of a changes also I; or flatten, which returns a copy of I, thus modifying a does not change I. However, note that both ravel and flatten returns a 1d array resulting in a size of (400,). The same order parameter should be used.
I want to use the function distanceTransform() to find the minimum distance of non-zero pixels to zeros pixels, but also the position of that closest zero pixel. I call the second version of the function with the labelType flag set to DIST_LABEL_PIXEL. Everything works fine and I get the distances to and indices of the closest zero pixels.
Now I want to convert the indices back to pixel locations and I thought the indexing would be like idx=(row*cols+col) or something like this but I had to find out that OpenCV is just counting the zero pixels and using this count as the index. So if I get 123 as the index of the closest pixel this means that the 123th zero pixel is the closest.
How is OpenCV counting them? Probably in a row-wise manner?
Is there an efficient way of mapping the indices back to the locations? Obviously I could recount them and keep track of the counts and positions, if I know how OpenCV counts them, but this seems stupid and not very efficient.
Is there a good reason to use the indexing they used? I mean, are there any advantages over using an absolute indexing?
Thanks in advance.
EDIT:
If you want to see what I mean, you can run this:
Mat mask = Mat::ones(100, 100, CV_8U);
mask.at<uchar>(50, 50) = 0;
Mat dist, labels;
distanceTransform(mask, dist, labels, CV_DIST_L2, CV_DIST_MASK_PRECISE, DIST_LABEL_PIXEL);
cout << labels.at<int>(0,0) << endl;
You will see that all the labels are 1 because there is only one zero pixel, but how am I supposed to find the location (50,50) with that information?
The zero pixels also get labelled - they will have the same label as the non-zero pixels to which they are closest.
So you will have a 2D array of labels, the same size as your source image. If you examine all of the zero pixels in the source image, you can then find the associated label from the 2D array returned. This can then allow you to find which non-zero pixels are associated with each zero pixel by matching the labels.
If you see what I mean.
In python you can use numpy to associate the labels and the coordinates:
import cv2
import numpy as np
# create an image with two 0-lines
a = np.ones((100,100), dtype=np.uint8)
a[50,:] = 0
a[:,70] = 0
dt,lbl = cv2.distanceTransformWithLabels(a, cv2.DIST_L2, 3, labelType=cv2.DIST_LABEL_PIXEL)
# coordinates of 0-value pixels
xy = np.where(a==0)
# print label id and coordinate
for i in range(len(np.unique(lbl))):
print(i,xy[0][i], xy[1][i])
I am trying to change the RGB for the overall image for a project. Currently I am working with a test file before I apply it to the actual Image. I want to test different values of RGB but would first like to start with the mean of all three. How would I go about doing this? I have other modules installed such as scipy, numpy, matplotlib, etc if those are needed. Thanks
from PIL import Image, ImageFilter
test = Image.open('/Users/MeganRCunninghan/Pictures/4th-of-July-Wallpaper.ppm')
test.show()
test.getrgb()
Assuming your image is stored as a numpy.ndarray (Test this with print type(test))...
Your image will be represented by an NxMx3 array. Basically this means you have a N by M image with a color depth of 3- your RGB values. Taking the mean of those 3 will leave you with an NxMx1 array, where the 1 is now the average intensity. Numpy does this very well:
test = test.mean(2)
The parameter given, 2, specifies the dimension to take the mean along. It could be either 0, 1, or 2, because your image matrix is 3 dimensional. This should return an NxM array. You basically will be left with a gray-scale, (color depth of 1) image. Try to show the value that gets returned! If you get Nx3 or Mx3, you know you have just taken the average along the wrong axis. Note that you can check the dimensions of a numpy array with:
test.shape
Shape will be a tuple describing the dimensions of your image.
I have a 3D vector field that I am storing in a vtkImageData object. The vtkImageData object contains two arrays:
a 3 component vtkDoubleArray (the vector x, y and z components)
a 1 component vtkDoubleArray containing a separate quantity
I would like to extract the corresponding elements of the two arrays, for which the values of the 1 component array lie within a certain range. Here's what I've tried:
vtkSmartPointer<vtkImageThreshold> threshold =
vtkSmartPointer<vtkImageThreshold>::New();
threshold->SetInputData(image);
threshold->SetInputArrayToProcess(1, image->GetInformation()); // 1 is the Energy array index
threshold->ThresholdBetween(1e-22, 2e-22);
threshold->Update();
vtkSmartPointer<vtkImageData> thresholdedImage = threshold->GetOutput();
I've also tried using vtkThresholdPoints but to no avail. Any suggestions would be much appreciated.
Looks like I can use this example:
vtkSmartPointer<vtkThresholdPoints> threshold =
vtkSmartPointer<vtkThresholdPoints>::New();
threshold->SetInputData(image);
threshold->ThresholdBetween(1e-21, 2e-21);
threshold->SetInputArrayToProcess(0, 0, 0,
vtkDataObject::FIELD_ASSOCIATION_POINTS, "Energy");
threshold->Update();
vtkSmartPointer<vtkPolyData> thresholded = threshold->GetOutput();
I didn't realise that this approach was applicable but it would seem so. This does change the type of my data from vtkImageData to vtkPolyData and I have very little idea what the arguments to vtkThresholdPoints::SetInputArrayToProcess() mean. However, it seems to do the job. I'd be happy to hear any alternative suggestions!
From time to time I have to port some Matlab Code to OpenCV.
Almost always there is a way to do it and an appropriate function in OpenCV. Nevertheless its not always easy to find.
Therefore I would like to start this summary to find and gather some equivalents between Matlab and OpenCV.
I use the Matlab function as heading and append its description from Matlab help. Afterwards a OpenCV example or links to solutions are appreciated.
Repmat
Replicate and tile an array. B = repmat(A,M,N) creates a large matrix B consisting of an M-by-N tiling of copies of A. The size of B is [size(A,1)*M, size(A,2)*N]. The statement repmat(A,N) creates an N-by-N tiling.
B = repeat(A, M, N)
OpenCV Docs
Find
Find indices of nonzero elements. I = find(X) returns the linear indices corresponding to the nonzero entries of the array X. X may be a logical expression. Use IND2SUB(SIZE(X),I) to calculate multiple subscripts from the linear indices I.
Similar to Matlab's find
Conv2
Two dimensional convolution. C = conv2(A, B) performs the 2-D convolution of matrices A and B. If [ma,na] = size(A), [mb,nb] = size(B), and [mc,nc] = size(C), then mc = max([ma+mb-1,ma,mb]) and nc = max([na+nb-1,na,nb]).
Similar to Conv2
Imagesc
Scale data and display as image. imagesc(...) is the same as IMAGE(...) except the data is scaled to use the full colormap.
SO Imagesc
Imfilter
N-D filtering of multidimensional images. B = imfilter(A,H) filters the multidimensional array A with the multidimensional filter H. A can be logical or it can be a nonsparse numeric array of any class and dimension. The result, B, has the same size and class as A.
SO Imfilter
Imregionalmax
Regional maxima. BW = imregionalmax(I) computes the regional maxima of I. imregionalmax returns a binary image, BW, the same size as I, that identifies the locations of the regional maxima in I. In BW, pixels that are set to 1 identify regional maxima; all other pixels are set to 0.
SO Imregionalmax
Ordfilt2
2-D order-statistic filtering. B=ordfilt2(A,ORDER,DOMAIN) replaces each element in A by the ORDER-th element in the sorted set of neighbors specified by the nonzero elements in DOMAIN.
SO Ordfilt2
Roipoly
Select polygonal region of interest. Use roipoly to select a polygonal region of interest within an image. roipoly returns a binary image that you can use as a mask for masked filtering.
SO Roipoly
Gradient
Approximate gradient. [FX,FY] = gradient(F) returns the numerical gradient of the matrix F. FX corresponds to dF/dx, the differences in x (horizontal) direction. FY corresponds to dF/dy, the differences in y (vertical) direction. The spacing between points in each direction is assumed to be one. When F is a vector, DF = gradient(F)is the 1-D gradient.
SO Gradient
Sub2Ind
Linear index from multiple subscripts. sub2ind is used to determine the equivalent single index corresponding to a given set of subscript values.
SO sub2ind
backslash operator or mldivide
solves the system of linear equations A*x = B. The matrices A and B must have the same number of rows.
cv::solve