I'm kinda confuse of the meaning of edge density. From the equation,
edge density = sum(x=1,w) sum(y=1,h) e(x,y)/N
where e is the edge map image (magnitude of vertical edge at (x,y)), there are two version of N.
1st version - N = w x h (width x height)
2nd version - N = number of non zero vertical edge pixel
What I don't understand is how can I calculate the edge density? Is it just summation of the white edges pixels?
Edited
Hi all, from what I understand from reading the paper given by #Gilgamesh, the N is the area of the region, width times its height but from the answer given it seems there is a conflict whereby N refers to number of non white pixels(black pixel). So, which is the correct one? Here is another reference on the N value calculating edge density.
basically the edge density is really just a (local) average density, which you can either calculate over binarized images or, more common, over grey scale images.
And yes, it is basically just summing up over both x and y coordinates in a subimage in most cases, see equation (1) here
http://ro.uow.edu.au/cgi/viewcontent.cgi?article=1517&context=infopapers
and averaging afterwards.
Regards,
G.
From what I understand about edge density, it is defined as where are the white pixels and is the total number of pixels i.e. .
cannot be the number of black pixels because the number could be arbitrary, ranging from zero to all pixels and the range of edge density will then be .
When is the area, the range will be which portrays just what we want, the places where edges are dense (or sparse depending on your requirement).
The edge map is the map of gradient magnitude (i.e. the length of the gradient vector). So the edge density is the average of the gradient magnitude over a neighborhood.
If you have a binary edge map where 0 means no-edge, 1 means edge (this can be obtained by thresholding the gradient magnitude), then the edge density is just the ratio of edge/non-edge pixels.
Related
I have to make a sinusoidal curve in an image to output an equal straight line in the resulting image.
An example of input sinusoidal image:
What I think is one solution should be:
Placing down the origin of x and y coordinates at the start of the curve, so we will have y=0 at the starting point. Then points on the upper limit will be counted as such that y= y-(delta_y) and for lower limits, y=y+(delta_y)
So to make upper points a straight line, our resulting image will be:
O[x,y-delta_y]= I[x,y];
But how to calculate deltaY for each y on horizontal x axis (it is showing the distance of curve points from horizontal axis)
Another solution could be, to save all information of the curve in a variable and to plot it as a straight line, but how to do it?
Since the curve is blue we can use information from the blue and red channels to extract the curve. Simply subtraction of red channel from blue channel will highlight the curve:
a= imread('kCiTx.jpg');
D=a(:,:,3)-a(:,:,1);
In each column of the image position of the curve is index of the row that it's value is the maximum of that column
[~,im]=max(D);
so we can use row position to shift each column so to create a horizontal line. shifting each column potentially increases size of the image so it is required to increase size of the image by padding the image from top and bottom by the size of the original image so the padded image have the row size of 3 times of the original image and padding value is 255 or white color
pd = padarray(a,[size(a,1) 0 0], 255);
finally for each channel cirshift each column with value of im
for ch = 1:3
for col = 1: size(a,2)
pd(:,col,ch) = circshift(pd(:,col,ch),-im(col));
end
end
So the result will be created with this code:
a= imread('kCiTx.jpg');
D=a(:,:,3)-a(:,:,1);
%position of curve found
[~,im]=max(D);
%pad image
pd = padarray(a,[size(a,1) 0 0], 255);
%shift columns to create a flat curve
for ch = 1:3
for col = 1: size(a,2)
pd(:,col,ch) = circshift(pd(:,col,ch),-im(col));
end
end
figure,imshow(pd,[])
If you are sure you have a sinusoid in your initial image, rather than calculating piece-meal offsets, you may as well estimate the sinusoidal equation:
amplitude = (yMax - yMin)/2
offset = (yMax + yMin)/2
(xValley needs to be the valley immediately after xPeak, alternately you could do peak to peak, but it changes the equation, so this is the more compact version (ie you need to see less of the sinusoid))
frequencyScale = π / (xValley - xPeak)
frequencyShift = xFirstZeroCrossRising
If you are able to calculate all of those, this is then your equation:
y = offset + amplitude * sin(frequencyScale * (x + frequencyShift))
This equation should be all you need to store from one image to be able to shift any other image, it can also be used to generate your offsets to exactly cancel your sinusoid in your image.
All of these terms should be able to be estimated from the image with relatively little difficulty. If you can not figure out how to get any of the terms from the image, let me know and I will explain that one in particular.
If you are looking for some type of distance plot:
Take your first point on the curvy line and copy it into your output image, then measure the distance between that point and the next point on the (curvy) line. Use that distance to offset (from the first point) that next point into the output image only along the x axis. You may want to do it pixel by pixel, or grab clumps of pixels through averaging or jumping (as pixel by pixel will give you some weird digital noise)
If you want to be cleaner, you will want to set up a step size which was sufficiently small to approximately match the maximum sinusoidal curvature without too much error. Then, estimate the distance as stated above to set up bounds and then interpolate each pixel between the start and end point into the image averaging into bins based on approximate position. IE if a pixel from the original image would fall between two bins in the output image, you would split it and add its weighted parts to those two bins.
I have some binary images that want to classify them base on shape of them in MATLAB. If they have circular or elliptical shape they belong to class one,if they have elliptical shape with dent in their boundary they belong to class two. I dont know how can I use this feature. Can any body help me with this?
You can use the eccentricity property in regionprops. From MATLAB documentation of eccentricity:
The eccentricity is the ratio of the distance between the foci of the ellipse and its major axis length. The value is between 0 and 1. (0 and 1 are degenerate cases. An ellipse whose eccentricity is 0 is actually a circle, while an ellipse whose eccentricity is 1 is a line segment.)
So as the value of eccentricity increases , the ellipse starts becoming flatter. Hence, at its maximum value = 1, it is a line segment.
To check if there is a dent in the ellipse, you can use check for convexity. Whenever there is a dent in an ellipse, it will be non-convex. In other words, if you try to fit a convex polygon, it won't be able to approximate the shape well enough. You can use convexArea property to check the same. From MATLAB documentation of convexArea:
Returns a p-by-2 matrix that specifies the smallest convex polygon that can contain the region. Each row of the matrix contains the x- and y-coordinates of one vertex of the polygon. Only supported for 2-D label matrices.
So you use bwlabel to create a 2-D label matrix from your binary image and then check the difference between the area of your binary image and the area of the fitted convex polygon. Measuring area could be as simple as counting pixels. You already know that the number pixels of your fitted convex polygon = p. Just take the absolute difference between p and the number of pixels in your original binary image. You should be able to easily set a threshold to classify into one of the two classes.
I think you can write the code for this. Hope this helps.
Working on 2D Rectangular Nesting. Need to find the utilization percentage of the material. Assuming i have the length, breadth, left-bottom position of each rectangle. What is the best way to determine the Boundary-Cut Utilization?
Objective:- To find the AREA under the RED Line.
Sample images attached to depict what i have done and what i need.
What i have done
what i need
Another Example image of rectangles packed with allowance
If you're interested in determining the total "area" underneath the red line, one suggestion I have is if you have access to the Image Processing Toolbox, simply create a binary image where we draw all of the rectangles on the image at once, fill all of the holes, then to determine the area, just determine the total sum of all of the binary "pixels" in the image. You said you have the (x,y) positions of the bottom-left corner of each rectangle, as well as the width and height of each rectangle. To make this compatible in an image context, the y axis is usually flipped so that the top-left corner of the space is the origin instead of the bottom-left. However, this shouldn't affect our analysis as we are simply reflecting the whole 2D space downwards.
Therefore, I would start with a blank image that is the same size as the grid you are dealing with, then writing a loop that simply sets a rectangular grid of coordinates to true for each rectangle you have. After, use imfill to fill in any of the holes in the image, then calculate the total sum of the pixels to get the area. The definition of a hole in an image processing context is any black pixels that are completely surrounded by white pixels. Therefore, should we have gaps that are surrounded by white pixels, these will get filled in with white.
Therefore, assuming that we have four separate variables of x, y, width and height that are N elements long, where N is the number of rectangles you have, do something like this:
N = numel(x); %// Determine total number of rectangles
rows = 100; cols = 200; %// Define dimensions of grid here
im = false(rows, cols); %// Declare blank image
%// For each rectangle we have...
for idx = 1 : N
%// Set interior of rectangle at location all to true
im(y(idx)+1:y(idx)+height(idx), x(idx)+1:x(idx)+width(idx)) = true;
end
%// Fill in the holes
im_filled = imfill(im, 'holes');
%// Determine total area
ar = sum(im_filled(:));
The indexing in the for loop:
im(y(idx)+1:y(idx)+height(idx), x(idx)+1:x(idx)+width(idx)) = true;
Is a bit tricky to deal with. Bear in mind that I'm assuming that y accesses the rows of the image and x accesses the columns. I'm also assuming that x and y are 0-based, so the origin is at (0,0). Because we access arrays and matrices in MATLAB starting at 1, we need to offset the coordinates by 1. Now, the beginning index for the row starts from y(idx)+1. We end at y(idx) + height(idx) because we technically start at y(idx)+1 but then we need to go up to height(idx) but then we also subtract by 1 as your coordinates begin at 0. Take for example a line with the width of 20, from x = 0 to x = 19. This width is 20, but we draw from 0, up to 20-1 which is 19. Because of the indexing starting at 1 for MATLAB, and the subtraction of 1 due to the 0 indexing, the +1 and -1 cancel, which is why we are just left with y(idx) + height(idx). The same can be said with the x coordinate and the width.
Once we draw all of the rectangles in the image, we use imfill to fill up the holes, then we can sum up the total area by just unrolling the whole image into a single vector and invoking sum. This should (hopefully) get what you need.
Now, if you want to find the area without the filled in holes (I suspect this is what you actually need), then you can skip the imfill step. Simply apply the sum on the im, instead of im_filled, and so:
ar = sum(im(:));
This will sum up all of the "white" pixels in the image, which is effectively the area. I'm not sure what you're actually after, so use one or the other depending on your needs.
Boundary-Cut Area without using Image Processing Toolbox.
The Detailed question description and answer could be found here
This solution is applicable only to Rectangular parts.
Does anyone have suggestions/algorithms on how to calculate the surface area of a skew quadrilateral? (I believe skew quadrilateral = a quadrilateral whose vertices are not planar)
If your quadrilateral is embedded in d dimensions, then you can calculate the height of the quadrilateral by projecting the vector passing through one of the parallel sides onto the line passing through the other two parallel sides and computing the projection's length between the two sides of the original direction, and then the area is the length of the projection vector multiplied by the length of the side you projected onto.
I am calculating mean and variance of my original and stego image to compare them
I am using grayscale BMP image for comaprison
image=imread("image name")
M = mean(image(:))
V = var((image(:)))
Is this is correct way fo calculating mean/var in MATLAB? My Variance is getting more than mean..
Any help appreciated..
These are indeed the correct way to calculate the mean and variance over all the pixels of your image.
It is not impossible that your variance is larger than the mean as both are defined in the following way:
mean = sum(x)/length(x)
variance = sum((x - mean(x)).^2)/(length(x) - 1);
For example, if you generate noise from a standard normal distribution with randn(N,1), you will get N samples, and if you calculate the mean and variance, you will get approximately 0 and 1. So there as well, your variance may well be larger than the mean.
Both have a totally different meaning: the mean gives you an idea where your pixels are (i.e. are they white, black, 50% gray, ...). The mean will give you an idea of what pixel color to choose to summarize the color of the complete image. The variance gives you an idea how the pixel values are spread: e.g. if your mean pixel value is 50% gray, are most of the other pixels also 50% gray (small variance) or do you have 50 black pixels and 50 white pixels (large variance)? So you could also view it as a way to get an idea how well the mean summarizes the image (i.e. with zero variance, most of the information is captured by the mean).
edit: For the RMS value (Root Mean Square) of a signal, just do what the definition says. In most cases you want to remove the DC component (i.e. the mean) before calculating the RMS value.
edit 2: What I forgot to mention was: it also makes little sense to compare the numerical value of the variance with the mean from a physical point of view. The mean has the same dimension as your data (in case of pixels, think of intensity), while the variance has the dimension of your data squared (so intensity^2). The standard deviation (std in MATLAB), which is the square root of the variance on the other hand has the same dimension as the data, so there you could make some comparisons (it is another question whether you should do such comparison).
If you are workign with RGB image (H x W x 3), you have to calculate mean and variance separately for each channel. In this case the mean pixel will also be 3-values vector.
for ch = 1:3
M(ch) = mean(reshape(img(:,:,ch),[],1));
V(ch) = var(reshape(img(:,:,ch),[],1));
end
MATLAB has function image. Avoid using it as a variable.