I am writing my own script/function in matlab without using built-in command, "imresize" but i am getting 3 output images instead of getting single one. I am sharing my code here also. Kindly someone spot out my mistake.
%zoomin out an imagge
originalImage = imread('imggerm1.jpg');
[origImRows, origImColumns] = size(originalImage);
newImage = zeros(origImRows/2, origImColumns/2);
newImRow = 1; newImColumn = 1;
for row = 1:2:origImRows
for column = 1:2:origImColumns
newImage(newImRow, newImColumn)=originalImage(row, column);
newImColumn = newImColumn+1;
end
newImRow = newImRow+1;
newImColumn = 1;
end
figure; imshow(originalImage);
figure; imshow(newImage/255);
This is because you originally reading a color image, where each pixel is encoded by 3 numbers. Try typing size(originalImage) and you will see that this array is 3 dimensional (the size of the last dimension is 3).
In your code the following line:
[origImRows, origImColumns] = size(originalImage);
Produces the result you don't expect: your origImColumns appears to be 3 times bigger.
Your code is easy to fix. Below I slightly changed 3 lines: #4, #6 and #11:
%zoomin out an imagge
originalImage = imread('1.jpg');
[origImRows, origImColumns,~] = size(originalImage);
newImage = zeros(origImRows/2, origImColumns/2,3);
newImRow = 1; newImColumn = 1;
for row = 1:2:origImRows
for column = 1:2:origImColumns
newImage(newImRow, newImColumn,:)=originalImage(row, column,:);
newImColumn = newImColumn+1;
end
newImRow = newImRow+1;
newImColumn = 1;
end
figure; imshow(originalImage);
figure; imshow(newImage/255);
I need to find the blobs from the below image.
The major problem is background. background doesn't have uniform intensity. I tried couple of things like thresholding and edge detection in MATLAB but couldn't able to find a better ways to segment out all spheroids. I need to extract the blobs and I need to find the area of each blobs. Does anyone know how to work-around with this kind of background?
Edit (07/02/17):
As suggested by Spektre I tried Following things in MATLAB.
Method 1:
img_original = imread('~/my_image.jpg'); %Read image
img_ch = single(img_original(:,:,2)); %Pick one channel( here its green)
g = fspecial('gaussian',200,100); %Kernel matrix to make the img blurr
con_img = conv2(img_ch,g,'same'); %2D convolution, this wil make the img blurr
sub_img = (con_img - img_ch); %Simple matrix subtraction
sub_img(sub_img <= 10) = 0; %Thresholding
sub_img(sub_img ~= 0) = 1;
fil_sub = imfill(sub_img,'holes'); %Fill the regions
imgfilt = imfilter(fil_sub, ones(3)); %run filter using 3by3 matrx
imgfilt(imgfilt < 8) = 0; %Reduce noisy pixels by thresholding
mfilt_img = (medfilt2(imgfilt)); %reduce unwanted pixels
img = img_ch;
img(mfilt_img ~= 0) = 255;
img2 = img_ch;
img2(img2 < 70) = 0; %Threshold for darker pixels which are left out from above methode.
img(img2 ==0) = 255;
disp_img = img_original(:,:,1);
disp_img(img ==255) = 255;
img_original(:,:,1) = disp_img;
figure, imshow(img_original)
I got the segments but still not good enough I think. This method gave good segments in the high intensity background, Even if I reduce the threshold value segments are not clear in the darker background and brightest pixels in the blobs are excluded.
Method 2:
img_original = imread('~/cancer_cells/Snap-10234.jpg'); %Read image
img_ch = single(img_original(:,:,2)); %Pick one channel( here its green)
clear new_matcel cur_img matcel avg_matrx
s=3; % Set size of the square window
mat_img = img_ch; % Working image channel
% resize the working matrix so that the dimensions matches
resize_img = resizem(mat_img,round(size(mat_img)/s)*s);
% convert matrix into small s x s matrix and save each in cells
window_c = ones(1,size(resize_img,1)/s) * s;
window_r = ones(1,size(resize_img,2)/s) * s;
mat_cel = mat2cell(resize_img,window_c,window_r);
new_matcel = cell(size(mat_cel)); % initialize new variable
% get the average value for each window and replace the actual by avg value
for i = 1:size(mat_cel,1)
for j = 1:size(mat_cel,2)
cur_img = mat_cel{i,j};
avg_value = mean(mean(cur_img));
new_matcel{i,j} = ones(s) * avg_value;
end
end
avg_matrx = cell2mat(new_matcel); % convert cells to matrix
image_sub = (abs(resize_img - avg_matrx)); % take the absolute difference
image_sub(image_sub < 7) = 0; % thresholding
image_sub(image_sub~=0) = 1;
image_sub = bwmorph(image_sub,'bridge');% fill gaps
image_sub = imfill(image_sub,'holes'); % fill the bounded regioons
% image_sub(image_sub == 1) = 255;
image_sub = resizem(image_sub,size(img_ch)); % resize to original size
disp_img = img_original(:,:,1);
disp_img(image_sub == 1) = 255;
img_original(:,:,1) = disp_img;
figure, imshow(img_original)
Much better segmented image:
even brighter pixels are included in the segment. Thanks to Spektre.
Is there a way to improve the above code? or any other idea to get more precise segments?
Thanks.
How could I perform hog feature extraction from image set of different dimensions? I am getting this error on last section.
''Subscripted assignment dimension mismatch.''
%% Change Directory
cd('C:\Users\inquisitive\Documents\MATLAB\hog_test');
%% Root Folder
rootFolder = fullfile('D:\HGDatabase');
%% Load Imagesets Database Directory
imgSets = imageSet(rootFolder,'recursive');
%%
{ imgSets.Description } % display all labels on one line
[imgSets.Count] % show the corresponding count of images
%% determine the smallest amount of images in a category
minSetCount = min([imgSets.Count]);
imgSets = partition(imgSets, minSetCount, 'randomize');
[imgSets.Count]
%% partioning into training and testing sets
[trainingSet, testSet] = partition(imgSets, 0.2, 'randomize');
*%%CAN'T I SKIP THIS SECTION AND DEFINE hog_16x16 ON LOOP ITSELF WHY I NEED TO PERFORM THIS AT FIRST WITH ONE IMAGE*
img = read(trainingSet(3), 4);
[hog_16x16, vis16x16] = extractHOGFeatures(img,'CellSize',[16 16]);
cellSize = [16 16];
hogFeatureSize = length(hog_16x16);
%%Extracting Hog Features
trainingFeatures = [];
trainingLabels = [];
for hand = 1:numel(trainingSet)
numImages = trainingSet(hand).Count;
features = zeros(numImages, hogFeatureSize, 'single');
for i = 1:numImages
img = read(trainingSet(hand), i);
% Apply pre-processing steps
lvl = graythresh(img);
img = im2bw(img, lvl);
features(i, :) = extractHOGFeatures(img, 'CellSize', cellSize);
end
labels = repmat(trainingSet(hand).Description, numImages, 1);
trainingFeatures = [trainingFeatures; features];
trainingLabels = [trainingLabels; labels ];
end
Other Query:
Which image format work best .jpg or .png? I thought .png would be better? Am i right?
I took some pictures and resize them by thinking that it may train in better way? Am i thinking right or wrong? Or is there nothing to do with different size of input. What would you suggest either to perform in same size or image sets with different dimensions.
CAN'T I SKIP FOLLOWING SECTION AND DEFINE hog_16x16 ON LOOP ITSELF WHY I NEED TO PERFORM THIS AT FIRST WITH ONE IMAGE? If i can skip how to deal with that case
img = read(trainingSet(3), 4);
[hog_16x16, vis16x16] = extractHOGFeatures(img,'CellSize',[16 16]);
cellSize = [16 16];
hogFeatureSize = length(hog_16x16);
You should ensure the dimensions of the image are the same as all images, then your extracted hog_16x16 features will have the same dimensions.
I am developing a template matching program in MATLAB. The code runs well, and finds the closest result. My first question, in this code, I am using the function corr2(). I would like to try a version using the formula (I tried to upload a picture of but I need 10 reputations).
I understand the formula itself, but I am not sure what variables should I use to use it. For example, what is exactly the m and n mean in my images where can I get them? In another words, what does the formula take as inputs?
Second question is, when I run the code I have now, it takes long, is there any thing I can change to speed it up?
Original = imread('Red.jpg'); % Read original image
Template = imread('temp.png'); % Read template image
OriDu = im2double(Original); % convert original image
TempDu = im2double(Template); % convert template
OriH = size(Original, 1); %height of the Original image
OriW = size(Original, 2); %width of the Original image
OriD = size(Original, 3); %colour depth
TempH = size(Template, 1); %height of the Template image
TempW = size(Template, 2); %width of the Template image
TempD = size(Template, 3); %colour depth
TempDu = reshape(TempDu, TempH*TempW, 3);
corr = 0; % to check the best correlation found
%% two for loops to go through the original image.
for i = 1:OriH-TempH
for j = 1:OriW-TempW
% take a segment of the original image( same size as the template size)
segment = OriDu(i: (i - 1) + TempH, j: (j - 1) + TempW, :);
segment = reshape(segment, TempH*TempW, 3);
output = corr2(TempDu, segment);
if output > corr
corr = output;
x = i;
y = j;
end
end
end
figure;
subplot(1,2,1), imshow(Template), title('Template');
subplot(1,2,2), imshow(OriDu(x:x+TempH, y:y+TempW, :)),title('Segment of the similar part');
I have an image in which I want to only keep the green part and convert the others to gray scale.
It seems from the colors in your image, that the greens are actually so close to grayscale that you'll be unable to see anything. Either way this is how you do it:
im = imread('houses.jpg');
s= (im(:,:,2)>im(:,:,1))&(im(:,:,2)>im(:,:,3));
dim = double(im);
r = abs(dim(:,:,2)-((dim(:,:,1))+dim(:,:,2)+dim(:,:,3))/3) < 3;
q = s|r;
imgs = rgb2gray(im);
imgs3(:,:,1) = imgs;
imgs3(:,:,2) = imgs;
imgs3(:,:,3) = imgs;
imout = zeros(size(im));
for i=1:size(im,1),
for j=1:size(im,2),
if q(i,j) == 0,
imout(i,j,:) = imgs3(i,j,:);
else,
imout(i,j,:) = im(i,j,:);
end
end
end
imshow(uint8(imout))
imwrite(uint8(imout),'output.jpg');
if you want to see something useful you would probably want to do the following
im = imread('houses.jpg');
s= (im(:,:,2)>im(:,:,1))&(im(:,:,2)>im(:,:,3));
dim = double(im);
r = abs(dim(:,:,2)-((dim(:,:,1))+dim(:,:,2)+dim(:,:,3))/3) < 3;
q = s|r;
imgs = rgb2gray(im);
imgs3(:,:,1) = imgs;
imgs3(:,:,2) = imgs;
imgs3(:,:,3) = imgs;
imout = zeros(size(im));
for i=1:size(im,1),
for j=1:size(im,2),
if q(i,j) == 0,
imout(i,j,:) = imgs3(i,j,:);
else,
imout(i,j,1) = im(i,j,1);
imout(i,j,2) = 255;
imout(i,j,3) = im(i,j,3);
end
end
end
imshow(uint8(imout))
imwrite(uint8(imout),'output.jpg');
which gives this as result:
It should be something like this:
gray_img = rgb2gray(img);
green_mask = img(:,:,2) > img(:,:,1) & img(:,:,2) > img(:,:,3);
gray_img3 = cat(3, gray_img, gray_img, gray_img);
green_mask3 = cat(3, green_mask, green_mask, green_mask);
output_img = gray_img3;
output_img(green_mask3) = img(green_mask3);
I didn't check it, but I'm quite sure it should do the work.
The only thing you might want to modify is the computation of the mask, currently it will include all pixels that are more green than red or blue, but you may want to be more (or less) specific in choosing which pixels to leave unchanged.
I would suggest to use a purely hue=based approach, as you are interested in a specific color.
My approach would be to convert your images to the HSV colorspace and check the Hue channel.
img=imread('houses.jpg');
hsv=rgb2hsv(img);
% find the white areas of the image
gray_part=hsv(:,:,3)>0.7;
% find the green areas of the image that are not white
green_part=hsv(:,:,1)>(30/360) & hsv(:,:,1)<(210/360) & ~gray_part;
% create the output image
outimg=(uint8(double(img).*repmat(green_part,[1 1 3])));
figure;
subplot(121); imshow(img);
subplot(122); imshow(outimg);
This will give you the following image (left: original, right: resulting masked image):
Of course, if you need to get the rest of the image in grayscale you may use the previous results as follows:
pixel(1,1,1)=0;pixel(1,1,2)=255;pixel(1,1,3)=0;
green_img=repmat(pixel,[size(img,1) size(img,2), 1]);
green_part=repmat(green_part,[1 1 3]);
gray_img=rgb2gray(uint8(double(img).*~green_part));
gray_img=double(repmat(gray_img,[1 1 3]));
outimg=uint8(green_part.*green_img + gray_img);
figure; imshow(outimg);
This will display the image shown below: