I have a grayscale image from which I need to find the top 0.1% brightest pixels.
I tried using a max function on 0.1% of the pixels but it is not giving me correct results.
Code:
[m,n]=size(image);
num_pixels=m*n;
pixels=floor(num_pixels*0.01)
Here, I got some 7000 number in my variable pixels. I am not getting how to sort these 7000 pixels because it is just giving me one count. I need to get all the pixel values of this count.
Can anybody suggest how to do this in MATLAB.
You can get the top intensity value this way:
sortedIntensityValues = sort(grayScaleImg(:)); % ascending order
numPixels = numel(sortedIntensityValues);
topIntensity = sortedIntensityValues(floor(numPixels*0.999));
This way (as mentioned in comments):
sortedIntensityValues = sort(grayScaleImg(:),'descend'); % descending order
numPixels = numel(sortedIntensityValues);
topIntensity = sortedIntensityValues(floor(numPixels*0.001));
Or, if you have the stats toolbox you can use the prtcile function to do it like this:
topIntensity = prctile(grayScaleImg(:),99.9);
Here's proof of concept using the third approach:
Create some code for you to test:
grayScaleImg = rand(4096,4096);
Obtain the intensity for which only 0.1% of pixels are brighter than.
topIntensity = prctile(grayScaleImg(:),99.9);
Locate the pixels with intensity greater than this (i.e. top 0.1%) and place in a logical index array for reference.
logicalIndices = grayScaleImg>topIntensity;
Related
I have a temperature range of 33 degrees to 64 degrees F. I'm trying to figure out the pixel position of 59 degrees along a y-axis that spans 600 pixels. This is for a column chart.
Full disclosure, this is homework that I've been grappling for a while and simply have not yet figured it out.
var scale = d3.scale.linear().domain([33,64]).range([0,64]);
scale(59) returns 53.677419354838705 which is the wrong answer.
600 - 53.677419354838705 is also the wrong answer.
What might I be missing?
Thank you.
The domain is the complete set of values, so in this case that is all of your temperatures, from 33 to 64. The range is the set of resulting values of a function, in this case the resulting values of scaling your temperatures from 0 to 600.
So you're almost there, you're just using the wrong range - in this case your range should be the span of your y-axis (0 - 600):
var scale = d3.scale.linear().domain([33, 64]).range([0, 600]);
Which will result in scale(59) giving an output of 503.2258064516129.
I am working on tone mapping operators in HDR. My question is very simple. I want to scatter plot large arrays on Matlab 2015Ra with computer specs core i5 20GB RAM. Only the scatter plot eats up the whole memory (around 92% of 20GB). I need some suggestion to plot tall arrays. I know Matlab 2018 has binscatter function but I have lower version. Thank you. Sample Code:
a=randn(21026304,1);
scatter(a,a);
Only this code eats up the all memory.
You can create a binscatter like function yourself with histcounts2!
Histcounts bins the data into an NxN array which you can then visualize with imshow... this is pretty memory-efficient as every bin only takes up a couple of bytes, regardless of the input size.
% Some (correlated) data
x = randn(1e6,1);
y = randn(1e6,1)+x;
% Count 32x32 bins
[N,ax,ay] = histcounts2(x,y,32);
% Some gradient
cmap = [linspace(1,0,16);
linspace(1,0.3,16);
linspace(1,0.5,16)].';
% Show the histogram
imshow(...
N,[],... % N contains the counts, [] indicated range min-max
'XData', ax, 'YData', ay, ... % Axis ticks
'InitialMagnification', 800,... % Enlarge 8x
'ColorMap', cmap... % The colormap
);
colorbar;
axis on;
title('bin-counts');
I have a cell array called output. Output contains matrices of size 1024 x 1024, type = double, grayscale. I would like to plot each matrix and its corresponding histogram on a single plot. Here is what I have so far:
for i = 1:size(output,2)
figure
subplot(2,1,1)
imagesc(output{1,i});
colormap('gray')
colorbar;
title(num2str(dinfo(i).name))
subplot(2,1,2)
[pixelCount, grayLevels] = imhist(output{1,i});
bar(pixelCount);
title('Histogram of original image');
xlim([0 grayLevels(end)]); % Scale x axis manually.
grid on;
end
The plot I get, however, seems to be faulty... I was expecting a distribution of bars.
I am somewhat lost at how to proceed, any help or suggestions would be appreciated!
Thanks :)
Based on the colorbar on your image plot the values of your image pixels range from [0, 5*10^6].
For many image processing functions, MATLAB assumes one of two color models, double values ranging from [0, 1] or integer values ranging from [0 255]. While the supported ranges are not explicitly mentioned in the imhist documentation, in the "Tips" section of the imhist documentation, there is a table of scale factors for different numeric types that hints at these assumptions.
I think the discrepancy between your image range and these models is the root of the problem.
For example, I load a grayscale image and scale the pixels by 1000 to approximate your data.
% Toy data to approximate your image
I = im2double(imread('cameraman.tif'));
output = {I, I .* 1000};
for i = 1:size(output,2)
figure
subplot(2,1,1)
imagesc(output{1,i});
colormap('gray')
colorbar;
subplot(2,1,2)
[pixelCount, grayLevels] = imhist(output{1,i});
bar(pixelCount);
title('Histogram of original image');
grid on;
end
The first image is using a matrix with the standard [0,1] double value range. The imhist calculates a histogram as expected. The second image is using a matrix with the scaled [0, 1000] double value range. imhist assigns all the pixels to the 255 bin since that is the maximum bin. Therefore, we need a method that allows us to scale the bins.
Solution : Use histogram
histogram is designed for any numeric type and range. You may need to fiddle with the bin edges to show the structures that you are interested in as it doesn't initialize bins the same way imhist does.
figure
subplot(2,1,1)
imagesc(output{1,2});
colormap('gray')
colorbar;
subplot(2,1,2)
histogram(output{1,2});
title('Histogram of original image');
grid on;
this is my question:
I want to know which and how many times is a value repeated in a interval of a vector array, I know that many people will tell me that use "hist", but I did it and the results isn't exact enough, let me show you in a picture my problem:
In the past picture, you can see in blue the "Data"; and I have used 3 kinds of values: 1st "Mode", 2nd "Mean" and finally "Most repeated value in Histogram" which means that I used something like [a,b]=hist(Data), then Mayor Value = b(a==max(a)) and is very important to do NOT use a predefined range; but this picture doesn't represent the most repeted values, so let me show you another pic, which is a closer view of the data:
That blue "Data", which vary between (0-0.5)E-5 approximately is the interval that I need to obtain, but as you can see, the others three values are not close enough. And "mode" value is just "0". I hope that you can help me to solve this problem, thanks by the way!.
Ok to be more clear, I add this new pic:
What exactly I'm looking for is to get an interval, like in this example I wrote manually 0.1 - 0.4 E-4 (in purple), so the function will say:
[A,B]=magicfunction(Data);
A=[0.1E-4 0.4E-4]; B=[123];
Where B=123 means the amount of data contained in that interval, as you can see I just ingress vector "Data", nothing else.
In the next link you can get the "Data":
https://drive.google.com/file/d/0B4WGV21GqSL5Vk0tRUdLNk5XVnc/edit?usp=sharing
isn't taking the max of a hist in a range what you want? you almost got it, you just didn't define the bins well. For example:
range=4750:5050;
[counts val]=hist(data(range),unique(data(range)));
most_repeated _value_in_range=val(counts==max(counts));
Edit:
Following the clarification, what you want is a statistical bound regarding the histogram width around it's maximum (most frequent value) , here's a solution:
[c, v]=hist(data,linspace(min(data),max(data),num_of_bins));
range=find(c>1/exp(1)*max(c)); % can be also c>0.5*max(c) etc...
A=[v(range(1)) v(range(end))];
B=sum(c(range));
Let's test with some fake data:
t=linspace(-50,50,1e3);
data=0.3*exp(-(t-30).^2)+0.2*exp(-(t-10).^2)+0.3*exp(-(t+10).^2)+0.01*randn(1,numel(t));
[c, v]=hist(data,linspace(min(data),max(data),numel(t)));
range=find(c>1/exp(1)*max(c));
A=[v(range(1)) v(range(end))];
B=sum(c(range));
plot(t,data,'b'); hold on
plot([min(t) max(t)],[A(1) A(1)] ,'--r');
plot([min(t) max(t)],[A(2) A(2)] ,'--r');
B
B =
518
Of course you can change the definition of "width" of the histogram, I took 1/e to 1/e you can take full width at half max (c>0.5*max(c)), or narrower according to the type of data used, etc...
The function below is designed based on several assumptions:
The "interval" of interest is close to 0.
The majority of the samples are small.
The basic idea is to first filter out the samples that are too big, and then define the interval based on the sorted array of the remaining samples.
function [A, B] = magicfunction(data)
% Assuming the outlier samples only exist in the positive side, some
% samples of big, positive values can be excluded in order to obtain a
% better estimation of "the interval". Here we exclude the
% samples that are greater than mean(A)+K1*std(A), where K1 is empirically
% selected as 1.0
K1 = 1.0;
filtered_data = data( data < mean(data)+K1*std(data));
sorted_data = sort(filtered_data);
% Define the interval in terms of the percentile in the
% sorted_data. Here the interval is empirically selected as [0, 0.75]
interval = [0 0.75];
% Map the percentile interval to the actual index in sorted_data.
% Note that interval_index(1) cannot be smaller than 1, and
% interval_index(2) cannot be greater than length(sorted_data)
interval_index = round( length(sorted_data)*interval );
interval_index(1) = max(1, interval_index(1));
interval_index(2) = min(length(sorted_data), interval_index(2));
% Assign output A in terms of the value in the sorted_data
A = sorted_data(interval_index)
% Assign output B
B = sum( data>A(1) & data<A(2) )
% Visualization
x = [1:length(data)];
figure;
subplot(211);
plot(x, data, ...
x, repmat(A(:)', length(data),1) ); grid on;
legend('data', 'lower bound', 'upper bound');
xlim([1 20000]);
subplot(212);
plot(x, data, ...
x, repmat(A(:)', length(data),1) ); grid on;
legend('data', 'lower bound', 'upper bound');
ylim([0, 3*10^-5]);
xlim([1 20000]);
Feeding the data provided in your question into the function yields the following plot:
You may want to empirically tune the two variables in the function to obtain the desired result.
K1
interval
I am developing a project of detecting vehicles' headlights in night scene. I am working on a demo on MATLAB. My problem is that I need to find region of interest (ROI) to get low computing requirement. My solution is calculating total intensity per row and if the row's intensity is below threshold, it is blacked.
[rows col] = size(img1);
sumValue=[];
sum1 = sum(sum(img1)/(rows*col));
for a=1:1:rows
sumValue = sum(img1(a,:))/col;
if (sumValue <sum1+40)
img1(a,:)=0;
end
end
And here is the result:
Now i want to save the bright parts of image in arrays or matrices so that i can delete the small bright parts and keep only large part. If anyone has any idea, plz give me some suggestions.
I'm sure this could be optimised a bit more.
new_im = zeros(size(im));
% Loop through each column
for c=1:1:size(im,2)
column = im(:,c);
% The first non-zero value in each column will be the top of the window
upper_candidates = find(column>0);
top = upper_candidates(1);
% The first zero value after that will be your lower boundary
lower_candidates = find(column(top:end) == 0);
bottom = lower_candidates(1);
% Insert each column into the new image
new_im = im(top:bottom,c);
end