Remove single cell from a matrix - matrix

I am trying to remove single cells which are NA from a matrix data. I need to keep all of the other data in the matrix. All I could do is removing all the rows and colomns if a single cell is NA.
#First I replaced all the data points that are higher than 600,000
adjusted_data<-apply(data, c(1,2), FUN = function(x){ ifelse (x > 600,000, NA, x) })
#now I need to remove these single cells which turned to NA.
adjusted_data<- na.omit(adjusted_data)
However, When I use this code, all the ROWs and COLUMNS are removed even if a single cell is NA.

Related

Separate labeled data

I have a matrix of the size n x p(n data points). Using MATLAB k-means algorithm gives me an n x 1 array, where each element specifies the label of the data point at the same position in the data matrix.
What is the best way to separate the original data into multiple matrices according to the label specified in the other array?
Example
data_points =
-0.0168 0.0689
-0.0064 -0.0632
0.0527 0.0509
-0.0468 0.0152
labels =
1
2
2
1
Thus the first and the last data point should be in a new array and the second and third should be in a new array.

How to detect a portion of an image based upon the matrix values?

I have a simple pcolor plot in Matlab (Version R 2016b) which I have uploaded as shown in the image below. I need to get only the blue sloped line which extends from the middle of the leftmost corner to the rightmost corner without hard-coding the matrix values.
For instance: One can see that the desired slope line has values somewhere approximately between 20 to 45 from the pcolor plot. (From a rough guess just by looking at the graph)
I'm applying the following code on the matrix named Slant which contains the plotted values.
load('Slant.mat');
Slant(Slant<20|Slant>50)=0;
pcolor(Slant); colormap(jet); shading interp; colorbar;
As one can see I hard-coded the values which I don't want to. Is there any method of detecting certain matrix values while making the rest equal to zero?
I used an other small algorithm of taking half the maximum value from the matrix and setting it to zero. But this doesn't work for other images.
[maxvalue, row] = max(Slant);
max_m=max(maxvalue);
Slant(Slant>max_m/2)=0;
pcolor(Slant); colormap(jet); shading interp; colorbar;
Here is another suggestion:
Remove all the background.
Assuming this "line" results in a Bimodal distribution of the data (after removing the zeros), find the lower mode.
Assuming the values of the line are always lower than the background, apply a logic mask that set to zeros all values above the minimum + 2nd_mode, as demonstrated in the figure below (in red circle):
Here is how it works:
A = Slant(any(Slant,2),:); % save in A only the nonzero data
Now we have A that looks like this:
[y,x] = findpeaks(histcounts(A)); % find all the mode in the histogram of A
sorted_x = sortrows([x.' y.'],-2); % sort them by their hight in decendet order
mA = A<min(A(:))+sorted_x(2,1); % mask all values above the second mode
result = A.*mA; % apply the mask on A
And we get the result:
The resulted line has some holes within it, so you might want to interpolate the whole line from the result. This can be done with simple math on the indices:
[y1,x1] = find(mA,1); % find the first nonzero row
[y2,x2] = find(mA,1,'last'); % find the last nonzero row
m = (y1-y2)/(x1-x2); % the line slope
n = y1-m*x1; % the intercept
f_line = #(x) m.*x+n; % the line function
So we get a line function f_line like this (in red below):
Now we want to make this line thicker, like the line in the data, so we take the mode of the thickness (by counting the values in each column, you might want to take max instead), and 'expand' the line by half of this factor to both sides:
thick = mode(sum(mA)); % mode thickness of the line
tmp = (1:thick)-ceil(thick/2); % helper vector for expanding
rows = bsxfun(#plus,tmp.',floor(f_line(1:size(A,2)))); % all the rows for each coloumn
rows(rows<1) = 1; % make sure to not get out of range
rows(rows>size(A,1)) = size(A,1); % make sure to not get out of range
inds = sub2ind(size(A),rows,repmat(1:size(A,2),thick,1)); % convert to linear indecies
mA(inds) = 1; % add the interpolation to the mask
result = A.*mA; % apply the mask on A
And now result looks like this:
Idea: Use the Hough transform:
First of all it is best to create a new matrix with only the rows and columns we are interested in.
In order to apply matlab's built in hough we have to create a binary image: As the line always has lower values than the rest, we could e.g. determine the lowest quartile of the brightnesses present in the picture (using quantile, and set these to white, everything else to black.
Then to find the line, we can use hough directly on that BW image.

Change pixel values on a line in MATLAB

I wish to set values on a line whose endpoints are returned by the hough transforms to zero. I have written the following code snippet
imshow(img);
hold on
img_black = img;
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2]; %line end points
[x, y] = bresenham(xy(1,1),xy(1,2),xy(2,1),xy(2,2)); %returns all points on the line
for i = 1:length(x)
plot(x(i),y(i),'*'); %to plot individual pixels on line itself
img_black(x(i),y(i),:) = [0,0,0]; %set rgb values to zero
end
end
Although the points plotted on the image below are as expected
The image where the corresponding pixel values are being set to zero is not as expected.
What is happening here?
It looks like you have mixed up x and y with rows and columns.
img_black(x(i), y(i),:)
Should be
img_black(y(i), x(i),:);
This is because the first dimension of img_black is rows (y) and the second dimension is columns (x).
The resulting image looks like it does because your lines go the wrong way and (sometimes) go outside the bounds of the original image, but MATLAB gladly expands your image (with zeros) and sets the values that you request, hence all the black pixels on the right.
NOTE: This switching back and forth between row, column and x,y is common throughout MATLAB's built-in functions and you should always be careful to note what the output is. A class example is meshgrid vs ndgrid outputs.

Algorithm required for maximizing number of squares fitting in rectangle with constraints

I need an algorithm which counts the maximum possible number of squares of length X which can be fitting inside a M x N rectangle with constraints of grid availability.
For example
when X = 2 and M = N = 8 (gray grids cannot be used)
We get maximum 10 squares fitting inside this rectangle.
like below solution there may be multiple solution spaces for maximum count.
Which algorithm can do it for me?
Is there any DP solution unlike polynomial?
Is there any name of such particular algorithm?
[NB: I assume greedy wont work here, if i am wrong correct me]
Let please describe whatever the best approach you know.
As requested, for X = 2 you can use DP with bitmasks. You can either proceed by columns or rows, so you usually take the smaller one. Let's assume that the minimum number is the number of columns.
You can do a DP in which the state is the current row, the current column and a bitmask telling which columns are blocked in the current row.
Let me explain it a bit with your example.
Original state: row = 0, column = 0, bitmask = 00000000.
Check if you can place a square in your current position, in this case you can. So the result will be max(1 + placing the square, not placing the square). If you can't, then you only have one option: not placing it.
In case you don't place the square, your next state is row = 0, column = 1, bitmask = 00000000. Notice that now the first bit is telling about the next row, not the current as we have already passed that column.
In case you place the square, your next state is row = 0, column = 2 (we jump two because of the square) and bitmask = 11000000. That bitmask tells you that the first two positions of the second row are already blocked.
Now let's consider a different state, row = 2, column = 4, bitmask = 11110000. This corresponds to the case of your solution when you are in the third row and the fifth column. The bitmask tells us that the four first cells of the next row are already blocked and that the four next cells of the current row are free.
So again, you check if you can place or not the square. The cells are not blocked, but the grid contains a marked cell, so you can't. The next state is then row = 2, column = 5, bitmask = 11110000. With that example I want you to notice that the bitmask doesn't tell you anything about cells blocked by the original grid, but just by your previous squares.
So every state is checked in constant time, thus the complexity of the algorithm is the number of states, which is O(NM * 2^(min(N, M))), sorry I forgot an extra factor in my comment.

How to detect a point above and below a region?

I have this image:
Where the red dots are coordinates that divide the different letters of this Arabic word segment.
I want to detect the dots above or below the areas between the dots.
The dots are (from left to right) = [81,183;80,217;83,275;83,314]
Now there is a dot above the letter between [81,183] and [80,217]. Similarly there are dots above section between [80,217] and [83,275] and dots below region [83,275] and [83,314].
What I want to do is suppose a dot is detected above a coordinate then that coordinate must be deleted.
Would it be possible to detect these in Matlab?
edit: Here is the original image
The first image is just a crop showing my region of interest
You can extract the coordinates of the individual objects with regionprops
Here is an example implementation:
im=rgb2gray(imread('http://i.stack.imgur.com/jic1X.jpg'));
P=regionprops(~im2bw(im), 'All');
Areas=cell2mat({P.Area});
Centroids=cell2mat({P.Centroid}');
Select only the points that have an area larger that 10 but smaller than 100:
Coord=Centroids(Areas< 100 & Areas > 10,:);
Monitor the dots found:
imshow(im);
hold on
for k=1:length(Coord)
plot(Coord(k,1), Coord(k,2), 'ro');
hold on
end
Result:
You can then sort the points with something like:
Aboves=Coord(Coord(:,2) < 80,:);
Belows=Coord(Coord(:,2) > 80,:);
From here, there are many ways of solving your problem, one option is the following:
dots=[81,183;80,217;83,275;83,314];
DetectDots=zeros(length(dots)-1, 1); % Creating a vector of zeros corresponding to the gaps between the elements in 'dots'
for k=1:size(dots,1)-1
if ~isempty(find((Aboves(:,1) > dots(k,2) & Aboves(:,1) < dots(k+1,2)))) %*
DetectDots(k)=1;
elseif ~isempty(find((Belows(:,1) > dots(k,2) & Belows(:,1) < dots(k+1,2))))
DetectDots(k)=-1;
else
DetectDots(k)=0;
end
end
The result is a vector DetectDots with value [1,1,-1] in this case that indicates that there are dots above between the two first point, and between the second and third point, and dots below between the third and last point of the vector dots.
*find returns a logical array with ones where the condition is met. isempty checks if the output of find has at least one element. As a result the condition is one if there is at least one element in the array Aboves or Belows that meets the criteria. ~ is the logical NOT, hence ~= means not equal. & is the logical AND. Note also that the coordinates between images and arrays are inverted in matlab.

Resources