I am trying to sum up all the values in a 400 x 640 image that are within a masked region using the roifilt2 function. I created a mask using roipoly and it is also stored as a 400 x 640 matrix with 0's in the cells I am uninterested in and 1's in the cells that I wish to sum up.
I was wondering how you would go about this, I have looked at the mathworks page for roifilt2 but I don't understand how to pass the sum function into this properly. This is what I'm trying:
fh = #(I)(sum(I,2));
I2 = roifilt2(I, mask, fh);
where I is my image and mask is my mask. I also keep getting the following error, even though my I and my mask are DEFINITELY the same size:
Error using roifilt2 (line 79)
The filtered image is not the same size as the original image.
Any help would be appreciated, Thanks!
The problem is that the sum changes the size of the output image, try by clearing all the values outside of the region then summing up
% Define the function you want to use as a filter.
% This function, named f, passes the input image x to the imsharpen
% function and specifies the strength of the sharpening effect
% by using the 'Amount' name-value pair argument.
% f simply puts the values to 0
f = #(x)x-x;
% Filter the ROI using the roifilt2 function and specifying the image, mask, and filtering function.
% This filter clears all the values which are not in the region of interest
interest_region = roifilt2(img, ~mask, f);
So the final sum of the values in your region will be:
img_sum = sum(interest_region,'all');
Anyway, as Raab70 wrote, you could multiply by the mask to obtain the same result without using roifilt2:
img_sum = sum(img.*mask,'all');
Related
I = imread ("lena.jpg");
%imshow(I);
K = I;
C = conv2(I, K);
imshow(C);
I am expecting something like the following as indicated in this link.
But, my octave output is blank:
What could be the possible reason?
And, how can I obtain the expected output?
imshow() expect values between [0-255]. After your convolution all your value are way above 255. So of course when you use imshow(C), matlab/octave do a type conversion using uint8(). All your value equal 255 and the result is a white image. (0 = black, 255 = white).
You also should take into account severals things:
add the option 'same' to your convolution to preserve the original size of your image: conv2(I,K,'same')
If you only apply the convolution like that, you will obtain a strong border effect, because the central values of your image will be multiplied more time than the values in the border of your image. You should add a compensation matrix:
border_compensation = conv2(ones(size(K)),ones(size(K)),'same')
C = conv2(I,K,'same')./border_compensation
Normalize the final result (Don't take into account the point 2. if you really want the kind of output that you pointed out in your question)
C = uint8(C/max(C(:))*255)
As the title says, the output I’m getting out of this function is incorrect. By incorrect I mean that the data are overflowing. How do I normalise the matrix correctly? Currently almost all of the pictures I get are white.
I called the function from another MATLAB file like this:
mask = [3,10,3;0,0,0;-3,-10,-3];
A = imread(“football.jpg”);
B = ConvFun(A,mask);
function [ image ] = ConvFun( img,matrix )
[rows,cols] = size(img); %// Change
%// New - Create a padded matrix that is the same class as the input
new_img = zeros(rows+2,cols+2);
new_img = cast(new_img, class(img));
%// New - Place original image in padded result
new_img(2:end-1,2:end-1) = img;
%// Also create new output image the same size as the padded result
image = zeros(size(new_img));
image = cast(image, class(img));
for i=2:1:rows+1 %// Change
for j=2:1:cols+1 %// Change
value=0;
for g=-1:1:1
for l=-1:1:1
value=value+new_img(i+g,j+l)*matrix(g+2,l+2); %// Change
end
end
image(i,j)=value;
end
end
%// Change
%// Crop the image and remove the extra border pixels
image = image(2:end-1,2:end-1);
imshow(image)
end
In a convolution, if you want the pixel value to stay in the same range
, you need to make the mask add up to 1. Just divide the mask by sum(mask(:)) after defining it. This is however, not the case you are dealing with.
Sometimes that is not the needed. For example if you are doing edge detection (like the kernel you show), you don't really care about maintaining the pixel values. In those cases, the plotting of unnormalized images is more the problem. You can always set the imshow function to auto select display range: imshow(image,[]).
Also, I hope this is homework, as this is the absolutely worst way to code convolution. FFT based convolution is about 100 times faster generally, and MATLAB has an inbuilt for it.
My goal is to create a heatmap in Matlab using an existing floor plan, and manually collected RF RSSI values.
I have marked numerical values (~30 to ~80) on a floor plan using pen and paper after recording signal strength in various areas of a building. I am looking to plot this in a heatmap overlay to the original floor plan.
What I have done is the following:
Google. YouTube. Man pages. My research has landed me accomplishing the following:
Importing an image to Matlab by asking the user to select a photo
Write it to the imread() function
Set an array the size of the image, all zeroed out
This is currently done manually, but not a concern right now
Manually placing, heatmap(x,y) = val; in locations marked on the original plan
I have found the x,y pixel coordinates from Photoshops info pallet
used a Gaussian low pass filter on the points set by heatmap()
The filter argument includes the image dimensions in pixels
At this point, I try to display the filtered heatmap()-ed points over the original floor plan. I am using the same dimensions for the filtering and the array made from the image size, in pixels. However, I am not getting the heatmap points to overlay where I specified by hard coding it.
The code is as follows:
%Import an image***********************************************
%Ask a user to import the image they want
%**************************************************************
%The commented out line will not show the file type when prompted to select
%an image
%[fn,pn] = uigetfile({'*.TIFF,*.jpg,*.JPG,*.jpeg,*.bmp','Image files'}, 'Select an image');
%This line will select any file type, want to restrict in future
[fn,pn] = uigetfile({'*.*','Image files'}, 'Select an image');
importedImage = imread(fullfile(pn,fn));
%Create size for heat map**************************************
%Setting the size for the map, see comments below
%**************************************************************
%What if I wanted an arbitrary dimension
%Or better yet, get the dimensions from the imported file
heatMap = zeros(1512,1080);
%Manually placing the heatmap values along a grid
%Want to set zones for this, maybe plot out in excel and use the cells to
%define the image size?
heatMap(328,84) = .38;
heatMap(385,132) = .42;
heatMap(418,86) = .40;
heatMap(340,405) = .60;
heatMap(515,263) = .35;
heatMap(627,480) = .40;
heatMap(800,673) = .28;
heatMap(892,598) = .38;
heatMap(1020,540) = .33;
heatMap(1145,684) = .38;
heatMap(912,275) = .44;
heatMap(798,185) = .54;
%Generate the Map**********************************************
%Making the density and heat map
%**************************************************************
gaussiankernel = fspecial('gaussian', [1512 1080], 60);
density = imfilter(heatMap, gaussiankernel, 'replicate');
%imshow(density, []);
oMask = heatmap_overlay(importedImage, density, 'summer');
set(figure(1), 'Position', [0 0 1512 1080]);
imshow(oMask,[]);
colormap(summer);
colorbar;
Any idea why the overlayed filter is offset and not where specified?
This can be reproduced by any image 1512 x 1080
Please let me know if you want the original image used
The array was off.
What I did was the following:
Output the density map only
Verified dimension sizes in the Matlab Workspace
I have noticed the array for the density, heatMap, importedImage and oMask were not all n x m size.
heatMap and importedImage were n x m, and importedImage and oMask were m x n.
I swapped the dimensions to all be n x m and now the image overlays just fine.
So I need to take the derivative of an image in the x-direction for this assignment, with the goal of getting some form of gradient. My thought is to use the diff(command) on each row of the image and then apply a Gaussian filter. I haven't started the second part because the first is giving me trouble. In attempting to get the x-derivative I have:
origImage = imread('TightRope.png');
for h = 1:3 %%h represents color channel
for i = size(origImage,1)
newImage(i,:,h) = diff(origImage(i,:,h)); %%take derivative of row and translate to new row
end
end
The issue is somewhere along the way I get the error 'Subscripted assignment dimension mismatch.'.
Error in Untitled2 (line 14)
newImage(i,:,h) = diff(origImage(i,:,h));
Does anyone have any ideas on why that might be happening and if my approach is correct for getting the gradient/gaussian derivative?
Why not use fspecial along with imfilter instead?
figure;
I = imread('cameraman.tif');
subplot 131; imshow(I); title('original')
h = fspecial('prewitt');
derivative = imfilter(I,h','replicate'); %'
subplot 132; imshow(derivative); title('derivative')
hsize = 5;
sigma = 1;
h = fspecial('gaussian', hsize, sigma) ;
gaussian = imfilter(derivative,h','replicate'); %'
subplot 133; imshow(gaussian); title('derivative + gaussian')
The result is the following one:
If your goal is to use diff to generate the derivative rather than to create a loop, you can just tell diff to give you the derivative in the x-direction (along dimension 2):
newImage = diff(double(origImage), 1, 2);
The 1 is for the first derivative and 2 is for the derivative along the second dimension. See diff.
As #rayryeng mentions in his answer, it's important to cast the image as double.
Given a N element vector, diff returns a N-1 length vector, so the reason why you are getting an alignment mismatch is because you are trying to assign the output of diff into an incorrect number of slots. Concretely, supposing that N is the total number of columns, you are using diff on a 1 X N vector which thus returns a 1 x (N - 1) vector and you are trying to assign this output as a single row into the output image which is expected to be 1 x N. The missing element is causing the alignment mismatch. diff works by taking pairs of elements in the vector and subtracting them to produce new elements, thus the reason why there is one element missing in the final output.
If you want to get your code working, one way is to pad each row of the image or signal vector with an additional zero (for example) as input into diff. Something like this could work. Take note that I'll be converting your image to double to allow the derivative to take on negative values:
origImage = imread('...'); %// Place path to image here and read in
origImage = im2double(origImage); %// Change - Convert to double precision
newImage = zeros(size(origImage)); %// Change - Create blank new image and populate each row per channel manually
for h = 1:3 %%h represents color channel
for ii = 1:size(origImage,1) %// Change - fixed for loop iteration
newImage(ii,:,h) = diff([0 origImage(ii,:,h)]); %// Change
end
end
Take note that your for loop was incorrect since it didn't go over every row... just the last row.
When I use the onion.png image that's part of the image processing toolbox:
...and when I run this code, I get this image using imshow(newImage,[]);:
Take note that the difference filter was applied to each channel individually and I changed the intensities per channel so that the smallest value gets mapped to 0 and the largest value gets mapped to 1. How you can interpret this image is that any areasthat have a non-black colour have some non-zero differences and hence there is some activity going on in those areas and any areas that have a dark / black colour means that there is no activity going on in those areas. Take note that we applied a horizontal filter, so if you wanted to do this vertically, you'd simply repeat the behaviour but apply this column-wise instead of row-wise as you did above.
I'm trying to write a function in matlab for averaging images (all of the same size and format (.png)). But it's not really working at the moment. The error i get is: "Error using +, Integers can only be combined with integers of the same class, or scalar doubles."
The code is below. The images are all resized to the same size, and have padding applied if the proportions aren't equal (padding is done with an alpha channel, to make the padding transparent). The images are all proper png's, and can be opened in photoshop etc. without errors.
If i understand correctly, you don't have to initialize or declare variables in matlab. Which is probably part of my problem. My normal (processing/java) approach would be to initialize containerAv to be of size (x, y, 3), add all the color values of all images to it, and then divide all values by the number of images. Giving you the average image.
I don't really know how to do this in matlab. What am i doing wrong? How do i rewrite this code so it gets me the rgb average image?
function imageCentroid(imageList, resizeFolder, outputFolder, x, y)
% local variable
centroidImage = zeros([x y 3]);
% loop through all images in the resizeFolder
for i=1:length(imageList)
% get filename and load image
fname = imageList(i).name;
container = imread([resizeFolder fname]);
% add container values to centroidImage
centroidImage = centroidImage + container;
end
% calculate mean image (divide by number of images)
centroidImage = centroidImage / length(imageList);
% save mean image
imwrite(centroidImage, [outputFolder 'centroid.png']);
end
Probably change:
container = imread([resizeFolder fname]);
to
container = im2double(imread([resizeFolder fname]));