I wanted to find the mode on a very large matrix. I have an image 256,256,150, with many values for each voxel (ie pixel in 3D), and I want the mode on the last axis, for each voxel. It does work with scipy.stats.mode(matrix, axis=3).
But now I want to do it, without counting the many zeros that are in the matrix. I tried by replacing the zeros by NaNs, and it works, but it becomes crazily slow.
How can I do? I found ideas with histograms and other stuff. But with scipy or numpy, is it directly possible?
Thanks!
Probably you want to use scipy.stats.mstats.mode, which is for masked arrays?
Related
I have an image as showin in '1'.
I applied Hessian filter to get the result '2'.
I applied Standard filter (stdfilt) in MATLAB to get the result as in '3'.
I wish to combine these two results into a single image such that:
the horizontal lines (noise in my case) are removed.
the hyperbolic areas are filled.
How could I obtain such a result?
Original (1):
Hessian (2):
stdfilt (3):
Last two without markups:
You can start by binarizing your image. I recommend opencv otsu threshold. it will be hard to solve this problem if gradients are present. After the image is binarized, you will need to fix bridging between the parabolas and the horizontal lines. I recommend morphological erosion, but I am still experimenting with this in my own projects. After that, you can use watershed or DBSCAN to flood-fill each region with a given marker or color. You can then filter out the horizontal lines by pixel count, since they will be much larger than a single parabola. If erosion+DBSCAN doesn't work reliably, you can look into opencv's connectedComponents function.
See:
https://iq.opengenus.org/connected-component-labeling/
https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html
https://docs.opencv.org/4.x/d3/db4/tutorial_py_watershed.html
I have 8 plots which I want to implement in my Matlab code. These plots originate from several research papers, hence, I need to digitize them first in order to be able to use them.
An example of a plot is shown below:
This is basically a surface plot with three different variables. I know how to digitize a regular plot with just X and Y coordinates. However, how would one digitize a graph like this? I am quite unsure, hence, the question.
Also, If I would be able to obtain the data from this plot. How would you be able to utilize it in your code? Maybe with some interpolation and extrapolation between the given data points?
Any tips regarding this topic are welcome.
Thanks in advance
Here is what I would suggest:
Read the image in Matlab using imread.
Manually find the pixel position of the left bottom corner and the upper right corner
Using these pixels values and the real numerical value, it is simple to determine the x and y value of every pixel. I suggest you use meshgrid.
Knowing that the curves are in black, then remove every non-black pixel from the image, which leaves you only with the curves and the numbers.
Then use the function bwareaopen to remove the small objects (the numbers). Don't forget to invert the image to remove the black instead of the white.
Finally, by using point #3 and the result of point #6, you can manually extract the data of the graph. It won't be easy, but it will be feasible.
You will need the data for the three variables in order to create a plot in Matlab, which you can get either from the previous research or by estimating and interpolating values from the plot. Once you get the data though, there are two functions that you can use to make surface plots, surface and surf, surf is pretty much the same as surface but includes shading.
For interpolation and extrapolation it sounds like you might want to check out 2D interpolation, interp2. The interp2 function can also do extrapolation as well.
You should read the documentation for these functions and then post back with specific problems if you have any.
I am trying to produce a plot of theta vs. omega (theta on the x-axis, omega on the y-axis) and the plot I am generating looks ok except for stray horizontal lines that seem to span from -pi to pi. Does anyone know what causes this to happen, or how to remove them?
Thanks
Unless you provide your code, we won't be able to provide the good answer. These methods might help, though:
If there are sufficient points on the plot, and they are dense in the plot and less dense on the unwanted lines, you can try to insert 'bx' into plot, so the graph would consist of only blue crosses that would possibly make lines invisible retaining the remaining graph.
You can convert all the unwanted points in the matrices to NaN either manually or by adding some command like A(A>2)=NaN.
I am trying to detect corners (x/y coordinates) in 2D scatter vectors of data.
The data is from a laser rangefinder and our current platform uses Matlab (though standalone programs/libs are an option, but the Nav/Control code is on Matlab so it must have an interface).
Corner detection is part of a SLAM algorithm and the corners will serve as the landmarks.
I am also looking to achieve something close to 100Hz in terms of speed if possible (I know its Matlab, but my data set is pretty small.)
Sample Data:
[Blue is the raw data, red is what I need to detect. (This view is effectively top down.)]
[Actual vector data from above shots]
Thus far I've tried many different approaches, some more successful than others.
I've never formally studied machine vision of any kind.
My first approach was a homebrew least squares line fitter, that would split lines in half resurivly until they met some r^2 value and then try to merge ones with similar slope/intercepts. It would then calculate the intersections of these lines. It wasn't very good, but did work around 70% of the time with decent accuracy, though it had some bad issues with missing certain features completely.
My current approach uses the clusterdata function to segment my data based on mahalanobis distance, and then does basically the same thing (least squares line fitting / merging). It works ok, but I'm assuming there are better methods.
[Source Code to Current Method] [cnrs, dat, ~, ~] = CornerDetect(data, 4, 1) using the above data will produce the locations I am getting.
I do not need to write this from scratch, it just seemed like most of the higher-class methods are meant for 2D images or 3D point clouds, not 2D scatter data. I've read a lot about Hough transforms and all sorts of data clustering methods (k-Means etc). I also tried a few canned line detectors without much success. I tried to play around with Line Segment Detector but it needs a greyscale image as an input and I figured it would be prohibitivly slow to convert my vector into a full 2D image to feed it into something like LSD.
Any help is greatly appreciated!
I'd approach it as a problem of finding extrema of curvature that are stable at multiple scales - and the split-and-merge method you have tried with lines hints at that.
You could use harris corner detector for detecting corners.
alt text http://internationalpropertiesregistry.com/Server/showFile.php?file=%2FUpload%2F02468.gif358455ebc982cb93b98a258fc4d6ee60.gif
Is there a simple solution in MATLAB?
Easy answer: NOPE
For very simple: read the image as grayscale, threshold, clean up and run it through an ocr program.
%# read the image
img = imread('http://internationalpropertiesregistry.com/Server/showFile.php?file=%2FUpload%2F02468.gif358455ebc982cb93b98a258fc4d6ee60.gif');
%# threshold
bw = img < 150;
%# clean up
bw = bwareaopen(bw,3,4);
%# look at it - the number 8 is not so pretty, the rest looks reasonable
figure,imshow(bw)
Then, figure out whether there is an OCR program that can help, such as this one
For even simpler:
%# read the image
[img,map] = imread('http://internationalpropertiesregistry.com/Server/showFile.php?file=%2FUpload%2F02468.gif358455ebc982cb93b98a258fc4d6ee60.gif');
%# display
figure,imshow(img,map)
%# and type out the numbers. It's going to be SO much less work than writing complicated code
For a simple one like that you can probably just run a median filter and ocr.
A median filter will, for every pixel in the image, look at the area around it, usually a 3x3 or 5x5 pixel area, determine the median pixel value in that area and set the pixel to that median value. In a block of the same colour nothing will happen, the whole area is the same colour as the pixel under consideration so the median i sthe same as the current value (or at least almost the same permitting slight colour variations. On the other hand noise pixels, i.e. a single pixel with a differently coloured area around it will simply disappear, since the median value of the area will be the colour of all the pixels around the noise pixel.
As for the ocr, or optical character recognition, I'd just use an existing program/library, it would certainly be possible to write an ocr algorithm in Matlab, but would be a much bigger exercise than writing a simple algorithm in an hour. You'd first need to read up on ocr techniques and algorithms.
Clean up the image
Separate each character into distinct images
Compare each character against a set of reference characters
The best matches are the most likely original character
You may consult this post. I succeeded in cracking a simpler CAPTCHA with the illustrated approach.