How to fix this on Matlab Index in position 2 exceeds array bounds? - matlab

I have this following code on my Matlab, now i am getting an index in position 2 exceeds array bounds. How can i improve it?
data = thingSpeakRead(929272, "NumMinutes", 100);
aveTemp = mean(data(:,2)); // This line is the one, i got two fields from my thingspeak channel
apiKey = 'O6P4N8AVZWKNGK5U';
alertURL = "https://api.thingspeak.com/alerts/send";
options = weboptions("HeaderFields",["ThingSpeak-Alerts-API-Key", apiKey]);
alertBody = sprintf("The temperature is %0.2fF.", aveTemp);
alertSubject = sprintf("! Temperature exceeded 60.0F!");
if avg_temperature > 60.0
webwrite(alertURL, "body", alertBody, "subject", alertSubject, options);
end

Related

OxyPlot: Display labels for max/min values on LinearColorAxis

I'm trying to display labels for maximum and minimum values on color axis.
I've created and LinearColorAxis object, set max and min values from result array.
Currenty max = 180, min = -180
var colorAxis = new LinearColorAxis();
colorAxis.Palette = result.GetPalette();
colorAxis.Position = AxisPosition.Right;
colorAxis.Maximum = result.Array.Max2D();
colorAxis.Minimum = result.Array.Min2D();
After that I can see the next graph:
Graph
But as you can see there are no labels for min and max values. How can I do that? And need to display label for it to see my 180 and -180 values. Step for axis can be changed when I have other result with other min and max values. But I should display labels of min/max values for all cases.

hot to get pixel per meter in matlab

I have a vector shapefile which is in unit of 'Meter' presenting boundary of overall Germany. I am converting it into raster format based on each pixel representing 300 Meters respectively. After conversion I accessed inmage information using imfinfo() in matlab. However the result is giving me the unit value is in "Inches" I am quite confused at the moment and do not know what to do to convert inches to meters as a pixel size unit. Would you please give me some idea?
`% Code
R6 = shaperead('B6c.shp');
%Nord
XN6 = double(R6(4).X); YN6 = double(R6(4).Y);
XN6min = min(XN6(XN6>0)); XNmax = max(XN6);
YN6min = min(YN6(YN6>0)); YNmax = max(YN6);
%Bayern
XB6 = double(R6(7).X); YB6 = double(R6(7).Y);
XB6min = min(XB6(XB6>0)); XB6max = max(XB6);
YB6min = min(YB6(YB6>0)); YB6max = max(YB6);
%Schleswig-Holstein
XSH6 = double(R6(9).X); YSH6 = double(R6(9).Y);
XSH6min = min(XSH6(XSH6>0)); XSH6max = max(XSH6);
YSH6min = min(YSH6(YSH6>0)); YSH6max = max(YSH6);
%Sachsen
XS6 = double(R6(6).X); YS6 = double(R6(6).Y);
XS6min = min(XS6(XS6>0)); XS6max = max(XS6);
YS6min = min(YS6(YS6>0)); YS6max = max(YS6);
dx = round(XS6max-XN6min);
dy = round(YSH6max-YB6min);
M = round((dx)/300);enter code here N = round((dy)/300);
A6 = zeros(M,N); %initiating image matrix based on 4 limiting States
%transformation from world to pixel coordinates
xpix_bw =(((XBW-XN6min)*M)/dx)';
ypix_bw =(((YBW-YB6min)*N)/dy)';
xbw6=round(xpix_bw); xbw6=xbw6(~isnan(xbw6));
ybw6=round(ypix_bw); ybw6=ybw6(~isnan(ybw6));
%line drawing
for i=1:1:length(xbw6)-1
j=i+1;
x1=xbw6(i); x2=xbw6(j); y1=ybw6(i); y2=ybw6(j);
nn=atan2((y2-y1),(x2-x1)); % azimuthal angle
if x2==x1
l=abs(y2-y1);
else
l = round((x2-x1)/cos(nn)); % horizontal distance
end
xx=zeros(l,1); %empty column
yy=zeros(l,1); %empty column
% creating line along slope distance
for i=1:1:l
xx(i)=round(x1+cos(nn)*i);
yy(i)=round(y1+sin(nn)*i);
A6(xx(i)+1,yy(i)+1) = 256;
end
end
imwrite(A6, 'Untitled_0506_300.tif','Resolution', 300);`

Most efficient way to track multiple small objects in MATLAB?

I am relatively new to image processing, and have never attempted to do anything with images in MATLAB, so forgive me if i am making some very rookie errors.
I am attempting to make a program that will track ants in a video. The video is taken from a stationary camera, and records the ants from a birds-eye perspective. I am having issues making reliable tracks of the ants however. Initially, i used the ForegroundDetection function, however there were multiple issues:
1.) Stationary ants were not detected
2.) There was too much overlap between objects (high levels of occlusion)
A friend of mine recommended having a larger gap between compared frames, so instead of subtracting frame 1 from frame 2, do frame 1 from frame 30 instead (1 second apart), as this will make the ants that do not move as much more likely to appear on the subtracted image.
Below is the code i have so far. It is a bit of a shot-in-the-dark attempt to solve the problem, as i am running out of ideas:
i = 1;
k = 1;
n = 1;
Video = {};
SubtractedVideo = {};
FilteredVideo = {};
videoFReader = vision.VideoFileReader('001.mp4',...
'ImageColorSpace', 'Intensity', 'VideoOutputDataType', 'uint8');
videoPlayer = vision.VideoPlayer;
blobby = vision.BlobAnalysis('BoundingBoxOutputPort', true, ...
'AreaOutputPort', true, 'CentroidOutputPort', true, ...
'MinimumBlobArea', 1);
shapeInserter = vision.ShapeInserter('BorderColor','White');
while ~isDone(videoFReader) %Read all frame of video
frame = step(videoFReader);
Video{1, i} = frame;
i = i+1;
end
%Perform subtraction
for j=1: 1: numel(Video)-60
CurrentFrame = Video{1,j};
FutureFrame = Video{1,j+60};
SubtractedImage = imsubtract(CurrentFrame, FutureFrame);
SubtractedVideo{1,j} = SubtractedImage;
ImFiltered = imgaussfilt(SubtractedImage, 2);
BWIm = im2bw(ImFiltered, 0.25);
FilteredVideo{1,j} = BWIm;
end
for a = n:numel(FilteredVideo)
frame = Video{1, n};
bbox = step(blobby, FilteredVideo{1, k});
out = step(shapeInserter, frame, bbox);
step(videoPlayer, out);
k = k+1;
end
currently, when i run the code, i get the following error on the line out = step(shapeInserter, frame, bbox):
'The Points input must be a 4-by-N matrix. Each column specifies a different rectangle and is of the form [row column height width].'
My questions is:
1.) Is this the best way to try and solve the problem I'm having? Is there potentially an easier solution?
2.) What does this error mean? How do i solve the issue?
I appreciate any help anyone can give, thank you!

Resize Frame for Optical Flow

I have problem with optical flow if the frame size have been manipulated in any way this gives me error. There are two options either change the resolution of the video at the beginning or somehow how change the frame size in a way that optical flow will work. I will want to add a cascade object to detect nose, mouth and eyes in further development therefore I need solution that will work for individual regions without necessary setting optical flow individually for those regions especially that a bounding box does not have a fixed size and it will displace itself slightly from frame to frame. Here is my code so far, the error is that it is exceeding matrix dimensions.
faceDetector = vision.CascadeObjectDetector();
vidObj = vision.VideoFileReader('MEXTest.mp4','ImageColorSpace','Intensity','VideoOutputDataType','uint8');
converter = vision.ImageDataTypeConverter;
opticalFlow = vision.OpticalFlow('ReferenceFrameDelay', 1);
opticalFlow.OutputValue = 'Horizontal and vertical components in complex form';
shapeInserter = vision.ShapeInserter('Shape','Lines','BorderColor','Custom','CustomBorderColor', 255);
vidPlayer = vision.VideoPlayer('Name','Motion Vector');
while ~isDone(vidObj);
frame = step(vidObj);
fraRes = imresize(frame,0.5);
fbbox = step(faceDetector,fraRes);
I = imcrop(fraRes,fbbox);
im = step(converter,I);
of = step(opticalFlow,im);
lines = videooptflowlines(of, 20);
if ~isempty(lines)
out = step(shapeInserter,im,lines);
step(vidPlayer,out);
end
end
release(vidPlayer);
release(VidObj);
UPDATE: I went and edited the function for optical flow which creates lines and this sorts out the some size issues however it is necessary to to input this manually for each object (so if there is any other way let me know). I think the best solution would be set a fixed size to cascadeObjectDetector, does anyone know how to do this? Or have any other idea?
faceDetector = vision.CascadeObjectDetector(); %I need fixed size for this
faceDetector.MinSize = [150 150];
vidRead = vision.VideoFileReader('MEXTest.mp4','ImageColorSpace','Intensity','VideoOutputDataType','uint8');
convert = vision.ImageDataTypeConverter;
optFlo = vision.OpticalFlow('ReferenceFrameDelay', 1);
optFlo.OutputValue = 'Horizontal and vertical components in complex form';
shapeInserter = vision.ShapeInserter('Shape','Lines','BorderColor','Custom', 'CustomBorderColor', 255);
while ~isDone(vidRead)
frame = step(vidRead);
fraRes = imresize(frame,0.3);
fraSin = im2single(fraRes);
bbox = step(faceDetector,fraSin);
I = imcrop(fraSin, bbox);
im = step(convert, I);
release(optFlo);
of = step(optFlo, im);
lines = optfloo(of, 50); %use videooptflowlines instead of (optfloo)
out = step(shapeInserter, im, lines);
imshow(out);
end

ILNumerics ILSurface Adjust Z values

Is there a way to manipulate the range of Z values for a Surface plot in a way that can preserve the original values so I can create a range slider with a min and max values from the GetLimits() method and then update the data array Z values so I can set new limits but move the slides back and forth to adjust the min/max Z value and see the plot adjust as I do it?
Given this code
ILArray<float> tempArray = ILMath.tosingle(myDoubleArray);
dataArray.a = tempArray;
var plotCube = ilPanel1.Scene.First<ILPlotCube>();
var surface = plotCube.First<ILFastSurface>();
surface.Update(Z: dataArray, colormap: new ILColormap(ILColormaps.ILNumerics));
ilPanel1.Refresh();
The MinValue and MaxValue controls are initialized like this.
float maxZ, minZ;
dataArray.GetLimits(out minZ, out maxZ);
var zRange = maxZ - minZ;
MinValue.Maximum = (decimal)maxZ;
MinValue.Minimum = (decimal)minZ;
MinValue.Value = (decimal)minZ;
MaxValue.Maximum = (decimal)maxZ;
MaxValue.Minimum = (decimal)minZ;
MaxValue.Value = (decimal)maxZ;
I want to be able to manipulate the Z values in the array like this
dataArray[dataArray < (float)MinValue.Value] = (float)MinValue.Value;
dataArray[dataArray > (float)MaxValue.Value] = (float)MaxValue.Value;
var plotCube = ilPanel1.Scene.First<ILPlotCube>();
var surface = plotCube.First<ILFastSurface>();
surface.Update(Z: dataArray, colormap: new ILColormap(ILColormaps.ILNumerics));
ilPanel1.Refresh();
The issue is that dataArray is being changed with new min/max values. How can I restore dataArray if you want to change back to a larger min/max? Do I just clone dataArray and use that to change the plot? Or is there a feature of ILArray that tracks changes and can restore the array?
The solution to this problem is to use a temporary array and clone the original array and then normalize the temporary array and update the surface with it.
float min = surface.GetRangeMinValue(AxisNames.CAxis) + minOffs;
float max = surface.GetRangeMaxValue(AxisNames.CAxis) + maxOffs;
ILArray<float> tempArray = _dataArray.C;
tempArray[tempArray < min] = min;
tempArray[tempArray > max] = max;
surface.Update(Z: tempArray);
_dataArray is a static property loaded once with the original data. Any updates are done with the code above