Image mosaic-ing in Matlab - image

I am trying to do some image analysis over tiles of a big tif image. I have already done the processing required in each of these tiles and in this step I have to create one mosaic out of these tifs. I read somewhere that I can use 'cat' function for this reason. As I am not really pro in programming I found it easy and tried to apply it. The tiles I have are about 154 tifs and I tried the cat over 4 of them and it works and now I should expand it over all the files. My problem now is to apply it over all the tifs. The codes for 4 of them was:
img1 = imread ('E:...\'a1.tif','tif');
img2 = imread ('E:...\'a2.tif','tif');
img3 = imread ('E:...\'a3.tif','tif');
img4 = imread ('E:...\'a4.tif','tif');
image1 = cat(2,img1,img3);
image2 = cat(2,img2,img4);
image3 = cat(1,image2,image1);
imshow(image3)
as you see in the code two by two should be stitch horizontally and the result would be stitch vertically to have the final image. M question is how through these amount of images I define which ones should be stitch first horizontally and then the resulted images stitch vertically. I would be really thankful if you guys could help me with it. Any other approaches would be welcome.

If tiles are of the same size you could concatenate them by operating on them as if they were plain matrices:
% dots-and-linebreak used for prettier formatting
concatenated_image = [ img1, img3; ...
img2, img4 ];
All tiles till ; are concatenated horizontally in one row, and rows are concatenated vertically to form final image.
Applying this principle you could join any number of preloaded images by doing this:
NUMBER_OF_IMAGES = 152; % divisible by 4
IMAGES_PER_LINE = 4;
concatenated_image = [];
for ii = 0 : (NUMBER_OF_IMAGES/IMAGES_PER_LINE)-1
one_row = [];
for jj = 1 : IMAGES_PER_LINE
% concatenate next image in this line
one_row = [ one_row eval(['img' num2str(4*ii+jj)]) ];
end
% add constructed row to the existing image
concatenated_image = [ concatenated_image; one_row ];
end
Instead of using variables named like imgN you should prefer using Matlab's cell arrays. You could then load all the images with:
imgs = {};
for ii = 1:154
imgs{ii} = imread (['E:...\a' num2str(ii) '.tif'],'tif');
end
Then you would have to change the above concatenation code to:
...
one_row = [ one_row imgs{4*ii+jj} ];
...

Related

Rice grain Segmentation in Matlab

I have an image of multiple rice grains in jpg format. I need to separate the individual rice grains into a separate images.
The input image is as below:
The resultant images should contain individual rice as below:
Currently I am using the following code:
close all;
BW = imread('img11_Inp','jpg');
L = bwlabel(BW)
figure
imshow(BW);
CC = bwconncomp(L);
stats = regionprops(L,'Image');
stats
%Display the first component as an image
Image1 = stats(2).Image
figure
imshow(Image1);
There are two problems with this code. Firstly, it is showing only two images rice grains in the "stats" structure and secondly it is also showing some noise. Please let me know what is the problem with this code
Look at this code with the comments
close all;
clear
I = imread('rice.jpg'); % jpg add noise. TODO: use png format
level = graythresh(I); % Global image threshold using Otsu's method
BW1 = imbinarize(I,level); % need to threshold, jpg add low level noise.
BW2 = imfill(BW1,'holes'); %fill holes inside grains
[L,n] = bwlabel(BW2); % label connected components
B = labeloverlay(I,L);
figure('Name',sprintf('NLables=%d',n)); imshow(B);
stats = regionprops(L,{'Centroid','Area'});
for i=1:length(stats)
x=stats.Centroid(i,1);
y=stats.Centroid(i,2);
area=stats.Area(i);
text(x,y,sprintf('Area=%d',area),'FontSize',8);
end

How do I read a RAW RGB image in MATLAB?

I am trying to properly convert a RAW image so that I can view it in MATLAB. Image can be downloaded here. I am using the version of the code provided in How can I read in a RAW image in MATLAB?
However, it is not working properly for me. Here is my slightly modified version below:
clear;
row=966; col=1296;
fin=fopen('C:\Users\user\Desktop\test2.raw','r');
I=fread(fin, col*row*3,'uint8=>uint8'); %// Read in as a single byte stream
I = reshape(I, [col row 3]); %// Reshape so that it's a 3D matrix - Note that this is column major
Ifinal = flipdim(imrotate(I, -90),2); % // The clever transpose
imshow(Ifinal);
fclose(fin); %// Close the file
What I get:
What I should get:
I'm not sure why it's not working for me but if I use an imaging program (ImageJ) I can correctly convert the RAW file if I select Image type as '24-bit BGR'. The pixel format of the image is 8 Bit BAYRG.
There you go:
function q43127920
row=966; col=1296;
fin=fopen('test.raw','r');
I = fread(fin, col*row*3,'ubit24=>uint32');
I = reshape(I, col, row, []);
B = uint8(bitand(bitshift(I,-00),uint32(255)));
G = uint8(bitand(bitshift(I,-08),uint32(255)));
R = uint8(bitand(bitshift(I,-16),uint32(255)));
I = cat(3,R,G,B);
Ifinal = flip(imrotate(I, -90),2);
imagesc(Ifinal);
fclose(fin);
Result:

Reading & Writing Grayscale TIF files in Matlab

I'm trying to extract a (very) large number of subimages from a large grayscale TIF file and save each image as a GIF, PNG, or even another TIF using MATLAB. I'm able to display the individual images using imshow(sub(:,:,1),cmap) but when I try to write the data to an image file, the generated files are just white squares 101x101 px. Using the cmap argument in imwrite produces the same result, as does changing the image format (I've tried with PNG, TIF, GIF, and JPG with no luck). The file a.tif is 16 bit according to the property menu in Windows Explorer. Any help is appreciated. I'm really at wit's end with this.
% Import coordinates array and correct for multiplication by 10
datafile = 'data.xlsx';
coords = xlsread(datafile,1,'G2:H13057');
x = coords(:,1) ./ 10;
y = coords(:,2) ./ 10;
r = 50;
[img, cmap] = imread('a.tif'); % import the image
s = 2*r+1; % scalar of size of each submatrix in the array (sise of image)
sub = zeros(s,s,num); % create 3D matrix/array of matrices. Each submatrix corresponds to 50 px box around each point
i = 1:4;
subrgb = zeros(s,s,num);
for i=1:4
sub(:,:,i) = img((y(i)-r):(y(i)+r),(x(i)-r):(x(i)+r));
filename = 'dot_%d.png';
filename = sprintf(filename,i);
imwrite(sub(:,:,i),filename,'png');
end
Try changing the line:
sub = zeros(s,s,num);
to:
sub = zeros(s,s,num,class(img));
I assume that the problem is that sub is of type double.
Good luck

Add padding to object in 4-channel image

I have a 4-channel image (.png, .tif) like this one:
I am using OpenCV, and I would like to add padding of type BORDER_REFLECT around the flower. copyMakeBorder is not useful, since it adds padding to the edges of the image.
I can add certain padding if I split the image in bgr + alpha and apply dilate with BORDER_REFLECT option on the bgr image, but that solution spoils all the pixels of the flower.
Is there any way to perform a selective BORDER_REFLECT padding addition on a ROI defined by a binary mask?
EDIT:
The result I expect is something like (sorry I painted it very quickly with GIMP) :
I painted two black lines to delimit the old & new contour of the flower after the padding, but of course those lines should not appear in the final result. The padding region (inside the two black lines) must be composed by mirrored pixels from the flower (I painted it yellow to make it understandable).
A simple python script to resize the image and copy the original over the enlarged one will do the trick.
import cv2
img = cv2.imread('border_reflect.png', cv2.IMREAD_UNCHANGED)
pad = 20
sh = img.shape
sh_pad = (sh[0]+pad, sh[1]+pad)
imgpad = cv2.resize(img, sh_pad)
imgpad[20:20+sh[0], 20:20+sh[1], :][img[:,:,3]==255] = img[img[:,:,3]==255]
cv2.imwrite("padded_image.png", imgpad)
Here is the result
But that doesn't look very 'centered'. So I modified the code to detect and account for the offsets while copying.
import cv2
img = cv2.imread('border_reflect.png', cv2.IMREAD_UNCHANGED)
pad = 20
sh = img.shape
sh_pad = (sh[0]+pad, sh[1]+pad)
imgpad = cv2.resize(img, sh_pad)
def get_roi(img):
cimg = img[:,:,3].copy()
contours,hierarchy = cv2.findContours(cimg,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
#Remove the tiny pixel noises that get detected as contours
contours = [cnt for cnt in contours if cv2.contourArea(cnt) > 10]
x,y,w,h = cv2.boundingRect(cnt)
roi=img[y:y+h,x:x+w]
return roi
roi = get_roi(img)
roi2 = get_roi(imgpad)
sh = roi.shape
sh2 = roi2.shape
o = ((sh2[0]-sh[0])/2, (sh2[1]-sh[1])/2)
roi2[o[0]:o[0]+sh[0], o[1]:o[1]+sh[1], :][roi[:,:,3]==255] = roi[roi[:,:,3]==255]
cv2.imwrite("padded_image.png", imgpad)
Looks much better now
The issue has been already addressed and solved here:
http://answers.opencv.org/question/90229/add-padding-to-object-in-4-channel-image/

image processing

I have this set of images as shown, I found the centroid of each by using the code below, now I stored the new images in Im01,Im02,Im03, and they are all N by N matrix images.
Im1 = imread('image1.png');
[x,y] = ait_centroid(Im1);
Im01=circshift(Im1, [-1 -5]);
[x,y] = ait_centroid(Im01);
Im01=uint16(Im01);
Im2 = imread('image2.png');
[x,y] = ait_centroid(Im2);
Im02=circshift(Im2, [-2 -4]);
[x,y] = ait_centroid(Im02);
Im02=uint16(Im02);
Im3 = imread('image3.png');
[x,y] = ait_centroid(Im3);
Im03=circshift(Im3, [-3 -5]);
[x,y] = ait_centroid(Im03);
Im03=uint16(Im03);
my challenge is how to add this images using iteration cos i hav a large set of images(not jst the 3 images) im working on.I was able to add them manually n show the mean by doin this
G=imadd(Im01,Im02,'uint16');
G=imadd(G,Im03,'uint16');
imshow(uint8(G/3),[]);
and it worked.But when I tried iterating by doin this
G=imadd(Im01,Im02,'uint16');
for i=1:1:3
G=imadd(G,Im(i),'uint16');
end
I get error, I also tired to define the images as a matrix of a matrix by
H = [ [Im01] [Im02] [Im03] ]
G=imadd(Im01,Im02,'uint16');
for i=1:1:3
G=imadd(G,H(i),'uint16');
end
error indicates in H(i).
The code is in Matlab
H = [ [Im01] [Im02] [Im03] ] does not create an array of matrices in Matlab. Instead, it catenates the three images into a single array. What you want to do is create a cell array, i.e. the following will work:
%# curly brackets to construct cell array
H = {Im01, Im02, Im03 };
G=H{1}; %# initialize G
for i=2:1:3 %# start at img#2
G=imadd(G,H{i},'uint16');
end
Alternatively, if all you want to do with the images is to add them, you can do the following:
%# in case you want to store the images
images = cell(numberOfImages,1);
%# loop over all images
for iImg = 1:numberOfImages
tmp = imread(sprintf('image%i.png',iImg));
[x,y] = ait_centroid(tmp);
Im01=circshift(tmp, [x y]); %# I assume that's what you want?
[x,y] = ait_centroid(Im01); %# not sure what you do this for
if iImg ==1
G = uint16(tmp);
else
G = imadd(G,uint16(tmp));
end
%# maybe you want to store your images
images{iImg} = uint16(tmp);
end
You can use sprintf and eval to iterate over the names of your images.
G=imadd(Im01,Im02,'uint16');
for i=1:1:3
Im_name = sprinft('Im0%i',i);
G=imadd(G,eval(Im_name),'uint16');
end
The sprintf function will add the number i behind the string 'Im0', so you will first get Im01, then Im02, etc.. The eval function is needed to interpret these strings into Matlab varibales.
EDIT: I think the best way to avoid problems like this is to save your images in a cell from the beginning. That is, when reading in the images, read them into one cell
Im{1} = imread('Im01.xxx')
Im{2} = imread('Im02.xxx')
etc...
you can then easily iterate over the different images without using strings.

Resources