I have a question about converting a height-map that is in colour into a matrix - look here to see examples of such maps. If I were to have a terrain plot and plot it using imagesc, then I would see it as a colour map. I was wondering how I could convert an image that looks like this into its corresponding matrix.
This seems like it should be a pretty basic procedure, but I can neither work out how to do it myself nor find out how to do it online (including looking on SO).
To put it another way, the image in question is a jpeg; what I'd like is to be able to convert the .jpg file into a matrix, M say, so that imagesc(M), or surf(M), with the camera looking at the (x,y)-plane (from above), give the same as viewing the image, eg imshow(imread('Picture.jpg')).
You can use Matlab's rbg2ind function for this. All you need to choose is the "resolution" of the output colormap that you want, i.e. the second parameter n. So if you specify n as 8 for example, then your colormap will only have 8 values and your output indexed image should only have 8 values as well.
Depending on the color coding scheme used, you might try first converting the RGB values to HSL or HSV and using the hue values for the terrain heights.
Let's say i have an image like that one:
After some quick messing around, i got a binary image of the axe, like that:
What is the easiest/fastest way to get the contour of that image using GNU/Octave?
In Octave you can use bwboundaries (but I will welcome patches that implement bwtraceboundaries)
octave:1> pkg load image;
octave:2> bw = logical (imread ("http://i.stack.imgur.com/BoQPe.jpg"));
octave:3> boundaries = bwboundaries (bw);
octave:4> boundaries = cell2mat (boundaries);
octave:5> imshow (bw);
octave:6> hold on
octave:7> plot (boundaries(:,2), boundaries(:,1), '.g');
There are a couple of differences here from #Benoit_11 answer:
here we get the boundaries for all the objects in the image. bwboundaries will also accept coordinates as input argument to pick only a single object but I believe that work should be done by further processing your mask (may be due to the jpeg artifacts)
because we get boundaries for all objects, so you get a cell array with the coordinates. This is why we are using dots to plot the boundaries (the default is lines and it will be all over the image as it jumps from one object to other). Also, it is not documented whether the coordinates given are for the continuous boundary, so you should not assume it (again, why we plot dots).
the image that is read seems to have some artifacts, I will guess that is from saving in jpeg.
You can use bwtraceboundary in the Image package. Here is the Matlab implementation but that should be pretty similar using Octave:
First estimate starting pixel to look for boundary and then plot (BW is the image). (Check here )
dim = size(BW);
col = round(dim(2)/2)-90;
row = min(find(BW(:,col)));
boundary = bwtraceboundary(BW,[row, col],'N');
imshow(BW)
hold on;
plot(boundary(:,2),boundary(:,1),'g','LineWidth',3);
Output:
Is it possible to clustering for RGB + spatial features of images with matlab?
NOTE: I want to use kmeans for clustering.
In fact basicly i want to do one thing, i want to get this image
from this
I think you are looking for color quantization.
[imgQ,map]= rgb2ind(img,4,'nodither'); %change this 4 to the number of desired colors
%in quantized image
imshow(imgQ,map);
Result:
Using kmeans :
%img is the original image
imgVec=[reshape(img(:,:,1),[],1) reshape(img(:,:,2),[],1) reshape(img(:,:,3),[],1)];
[imgVecQ,imgVecC]=kmeans(double(imgVec),4); %4 colors
imgVecQK=pdist2(imgVec,imgVecC); %choosing the closest centroid to each pixel,
[~,indMin]=min(imgVecQK,[],2); %avoiding double for loop
imgVecNewQ=imgVecC(indMin,:); %quantizing
imgNewQ=img;
imgNewQ(:,:,1)=reshape(imgVecNewQ(:,1),size(img(:,:,1))); %arranging back into image
imgNewQ(:,:,2)=reshape(imgVecNewQ(:,2),size(img(:,:,1)));
imgNewQ(:,:,3)=reshape(imgVecNewQ(:,3),size(img(:,:,1)));
imshow(img)
figure,imshow(imgNewQ,[]);
Result of kmeans :
If you want to add distance constraint to kmeans, the code will be slightly different. Basically, you need to concatenate pixel coordinates of corresponding pixel vales too. But remember, while assigning nearest centroid to each pixel, assign only the color i.e. the first 3 dimensions, not the last 2. That doesn't make sense, obviously. The code is very similar to the previous, please note the changes and understand them.
[col,row]=meshgrid(1:size(img,2),1:size(img,1));
imgVec=[reshape(img(:,:,1),[],1) reshape(img(:,:,2),[],1) reshape(img(:,:,3),[],1) row(:) col(:)];
[imgVecQ,imgVecC]=kmeans(double(imgVec),4); %4 colors
imgVecQK=pdist2(imgVec(:,1:3),imgVecC(:,1:3));
[~,indMin]=min(imgVecQK,[],2);
imgVecNewQ=imgVecC(indMin,1:3); %quantizing
imgNewQ=img;
imgNewQ(:,:,1)=reshape(imgVecNewQ(:,1),size(img(:,:,1))); %arranging back into image
imgNewQ(:,:,2)=reshape(imgVecNewQ(:,2),size(img(:,:,1)));
imgNewQ(:,:,3)=reshape(imgVecNewQ(:,3),size(img(:,:,1)));
imshow(img)
figure,imshow(imgNewQ,[]);
Result of kmeans with distance constraint:
Lets think, I would take a picture of a sheet on a table in an angle, that is not frontal. Of course, I will have a perspectivly stretched image.
Does anyone know an easy algorithm to "normalize" the area again to a sqared one, when all 4 edges/edgepoints in the source (taken photo) are defined/maybe clicked by the user?
The interpolation may be easy, I do not need algorithms to have smooth borders, nearest neighbour is enough (so, simply copying the pixel from the source position, which meets the rounded value from the calculated according pixel, ignoring the after-commas).
OpenCV has it all.
Basically, you get the 4 points and use
http://docs.opencv.org/modules/imgproc/doc/geometric_transformations.html#getperspectivetransform
(which basically inverts a matrix inside) to obtain the perspective transformation matrix, and then use
http://docs.opencv.org/modules/imgproc/doc/geometric_transformations.html#warpperspective
to apply the perspective transformation on the image.
The algorithms inside the latter can be found in http://en.wikipedia.org/wiki/Texture_mapping
I implemented the Spatial Pyramid Matching algorithm designed by
Lazebnik in Matlab and the last step is to do the svm
classification. And at this point I totally don't understand how I
should do that in terms of what input I should provide to the svmtrain and
svmclassify functions to get the pairs of feature point coordinates of
train and test image in the end.
I have:
coordinates of SIFT feature points on the train image
coordinates of SIFT feature points on the train image
intersection kernel matrix for train image
intersection kernel matrix for test image.
Which of these I should use?
A SVM classifier expects as input a set of objects (images) represented by tuples where each tuple is a set of numeric attributes. Some image features (e.g. gray level histogram) provides an image representation in the form of a vector of numerical values which is suitable to train a SVM. However, feature extraction algorithms like SIFT will output for each image a set of vectors. So the question is:
How can we convert this set of feature vectors to a unique vector that represents the image?
To solve this problem, you will have to use a technique that is called bag of visual words.
The problem is that number of points is different, SVM expects feature vector to be the same size for train and for test.
coordinates of SIFT feature points on the train image coordinates of
SIFT feature points on the train image
The coordinates won't help for SVM.
I would use:
the number of found SIFT feature points
segment the images in small rects and use the presence of a SIFT-Feature point in a
particular rect as boolean feature value. The feature is then the rect/SIFT-feature type
combination. for N-Rects and M-SIFt feature point types you obtain
N*M features.
The second approach requires spatial normalization of images - same size, same rotation
P.S.: I'm not expert in ML. I've only done some experiments on cell-recognition in microscope images.