The mask codes appear different for same label in different images in fastai lesson 3-camvid.ipynb example. Is this an issue? - semantic-segmentation

I'm trying the fastai example, lesson 3-camvid.ipynb, and there is a verification in the beginning of the example, about the images and labels. Where we can see the original image and a mask (ground thruth semantic segmentation) from that original image.
Example, image 150 from the camvid dataset:
img_f = fnames[150]
img = open_image(img_f)
img.show(figsize=(5,5))
get_y_fn = lambda x: path_lbl/f'{x.stem}_P{x.suffix}'
mask = open_mask(get_y_fn(img_f))
mask.show(figsize=(5,5), alpha=1)
But, if I change the image, for example to image 250 from the camvid dataset:
The mask label changes, eg. the road label has a different color from the previous image:
Apparently, it matters the order in which each label occurs on each image.
So, is this an issue? Is it something I should fix somehow?
Thanks in advance!

According to the official CamVid labels Road has to be the color as in the image 250.
Camvid Class Labels
You can leave the data set as it is, but if you looking for increasing model accuracy you can change the labels of the corresponding pixels. The Model is capable of identifying the road by other examples in data set.

Related

How should I interpret this neural network output?

My code:
organelleGroundTruth = selectLabels(gTruth,'organelle');
trainingData = objectDetectorTrainingData(organelleGroundTruth);
acfDetector = trainACFObjectDetector(trainingData,'NegativeSamplesFactor',2);
I = imread('test1.png');
bboxes = detect(acfDetector,I);
I = insertObjectAnnotation(I,'rectangle',bboxes,'');
imshow(I)
I used Image Labeler to label 21 .png images; as shown here:
I exported these into Matlab as "gTruth" (class is ground truth), and the only label name is "organelle" (because all of the white spots are organelles that I want to detect).
I tested the network on this image:
This is what the program gave me:
.
My first thought is that I labeled not enough images, so the neural network isn't as accurate as it would be with a larger labeled sample size.
However, I expected each white spot to be inside 1 large rectangle. Instead, the program placed a high number of small rectangles on the objects.
This is my main question: why are the rectangles so small, and can I tweak that? I think that I can solve the accuracy problem by labeling more images, but I don't know why the rectangles that the program produces are so small.
Edit: I accidentally called this a neural network - it is an object detector.
After more reading/tinkering, I've come to the conclusion that I need far, far more samples. Matlab's built in object detectors need thousands of sample images (particularly for samples so small in size) to be accurate.

Subtract background in image with Matlab

I have a list of images that i expect to have uneven illumination across the x axis only. The background estimation/model will be calculated in advance but only its shape will be given (so i will not have an empty background image that i can just subtract), I will just have the form/shape of it (for example linear).
Is there a way to subtract the background and get an even illumination of the image with just knowing its shape (and without having an actual background image)? I have attached an image from the Matlab library that was created using a linear background (background=-3*x+0.5). Can someone show me how to go from this example to the original image with just using the background shape?
I am also including the original image.
If you have the shape, and the conditions you state are correct, then you have the full background information. It is, however, not possible to undo the clipping that happened (where the image has values 255, you don't know what the original value was).
This is how you would create a background image given the shape:
img = imread('https://i.stack.imgur.com/0j2Gi.jpg');
img = img(27:284,91:370); % OP posted a screen shot? What is this margin?
x = 0:size(img,2)-1;
background = 0.3*x+0.5;
background = repmat(background,size(img,1),1);
imshow(img-background)
The results looks not exactly like the original image, but most of that can be explained by the clipping.
I replaced your -3*x+0.5 with 0.3*x+0.5 because the -3 makes no sense, and 0.3 makes it so that the background values remain in a meaningful range.
If, on the other hand, you are asking about fitting the linear model to the image data and estimating the exact background to subtract, then the problem is a bit more difficult, but not impossible. You can, for example, make an assumption about intensity uniformity across the x-axis if the illumination had been uniform across the image. You can then take the mean intensity along the x-axis and fit your model to it:
meanintensity = mean(img,1)';
plot(m)
X = [ones(length(meanintensity),1),(0:length(meanintensity)-1)']; % meanintensity = X*params
params = X\meanintensity;
hold on, plot(X*params)
background = X*params;
background = repmat(background',size(img,1),1);
imshow(img-background)

Interpolation between two images with different pixelsize

For my application, I want to interpolate between two images(CT to PET).
Therefore I map between them like that:
[X,Y,Z] = ndgrid(linspace(1,size(imagedata_ct,1),size_pet(1)),...
linspace(1,size(imagedata_ct,2),size_pet(2)),...
linspace(1,size(imagedata_ct,3),size_pet(3)));
new_imageData_CT=interp3(imagedata_ct,X,Y,Z,'nearest',-1024);
The size of my new image new_imageData_CT is similar to PET image. The problem is that data of my new image is not correct scaled. So it is compressed. I think the reason for that is that the pixelsize between the two images is different and not involved to the interpolation. So for example :
CT image size : 512x512x1027
CT voxel size[mm] : 1.5x1.5x0.6
PET image size : 192x126x128
PET voxel size[mm] : 2.6x2.6x3.12
So how could I take care about the voxel size regarding to the interpolation?
You need to perform a matching in the patient coordinate system, but there is more to consider than just the resolution and the voxel size. You need to synchronize the positions (and maybe the orientations also, but this is unlikely) of the two volumes.
You may find this thread helpful to find out which DICOM Tags describe the volume and how to calculate transformation matrices to use for transforming between the patient (x, y, z in millimeters) and volume (x, y, z in column, row, slice number).
You have to make sure that the volume positions are comparable as the positions of the slices in the CT and PET do not necsesarily refer to the same origin. The easy way to do this is to compare the DICOM attribute Frame Of Reference UID (0020,0052) of the CT and PET slices. For all slices that share the same Frame Of Reference UID, the position of the slice in the DICOM header refers to the same origin.
If the datasets do not contain this tag, it is going to be much more difficult, unless you just put it as an assumption. There are methods to deduce the matching slices of two different volumes from the contents of the pixel data referred to as "registration" but this is a science of its own. See the link from Hugues Fontenelle.
BTW: In your example, you are not going to find a matching voxel in both volumes for each position as the volumes have different size. E.g. for the x-direction:
CT: 512 * 1.5 = 768 millimeters
PET: 192 * 2.6 = 499 millimeters
I'll let to someone else answering the question, but I think that you're asking the wrong one. I lack context of course, but at first glance Matlab isn't the right tool for the job.
Have a look at ITK (C++ library with python wrappers), and the "Multi-modal 3D image registration" article.
Try 3DSlicer (it has a GUI for the previous tool)
Try FreeSurfer (similar, focused on brain scans)
After you've done that registration step, you could export the resulting images (now of identical size and spacing), and continue with your interpolation in Matlab if you wish (or with the same tools).
There is a toolbox in slicer called PETCTFUSION which aligns the PET scan to the CT image.
you can install it in slicer new version.
In the module's Display panel shown below, options to select a colorizing scheme for the PET dataset are provided:
Grey will provide white to black colorization, with black indicating the highest count values.
Heat will provide a warm color scale, with Dark red lowest, and white the highest count values.
Spectrum will provide a warm color scale that goes cooler (dark blue) on the low-count end to white at the highest.
This panel also provides a means to adjust the window and level of both PET and CT volumes.
I normally use the resampleinplace tool after the registration. you can find it in the package: registration and then, resample image.
Look at the screensht here:
If you would like to know more about the PETCTFUSION, there is a link below:
https://www.slicer.org/wiki/Modules:PETCTFusion-Documentation-3.6
Since slicer is compatible with python, you can use the python interactor to run your own code too.
And let me know if you face any problem

Detecting text in image using MSER

I'm trying to follow this tutorial http://www.mathworks.com/help/vision/examples/automatically-detect-and-recognize-text-in-natural-images.html to detect text in image using Matlab.
As a first step, the tutorial uses detectMSERFeatures to detect textual regions in the image. However, when I use this step on my image, the textual regions aren't detected.
Here is the snippet I'm using:
colorImage = imread('demo.png');
I = rgb2gray(colorImage);
% Detect MSER regions.
[mserRegions] = detectMSERFeatures(I, ...
'RegionAreaRange',[200 8000],'ThresholdDelta',4);
figure
imshow(I)
hold on
plot(mserRegions, 'showPixelList', true,'showEllipses',false)
title('MSER regions')
hold off
And here is the original image
and here is the image after the first step
[![enter image description here][2]][2]
Update
I've played around with parameters but none seem to detect textual region perfectly. Is there a better way to accomplish this than tweaking numbers? Tweaking the parameters won't work for wide array of images I might have.
Some parameters I've tried and their results:
[mserRegions] = detectMSERFeatures(I, ...
'RegionAreaRange',[30 100],'ThresholdDelta',12);
[mserRegions] = detectMSERFeatures(I, ...
'RegionAreaRange',[30 600],'ThresholdDelta',12);
Disclaimer: completely untested.
Try reducing MaxAreaVariation, since your text & background have very little variation (reduce false positives). You should be able to crank this down pretty far since it looks like the text was digitally generated (wouldn't work as well if it was a picture of text).
Try reducing the minimum value for RegionAreaRange, since small characters may be smaller than 200 pixels (increase true positives). At 200, you're probably filtering out most of your text.
Try increasing ThresholdDelta, since you know there is stark contrast between the text and background (reduce false positives). This won't be quite as effective as MaxAreaVariation for filtering, but should help a bit.

Extract Rectangular Image from Scanned Image

I have scanned copies of currency notes from which I need to extract only the rectangular notes.
Although the scanned copies have a very blank background, the note itself can be rotated or aligned correctly. I'm using matlab.
Example input:
Example output:
I have tried using thresholding and canny/sobel edge detection to no avail.
I also tried the solution given here but it detects the entire image for cropping and it would not work for rotated images.
PS: My primary objective is to determine the denomination of the currency. There are a couple of methods I thought I could use:
Color based, since all currency notes have varying primary colors.
The advantage of this method is that it's independent of the
rotation or scale of the input image.
Detect the small black triangle on the lower left corner of the note. This shape is unique
for each denomination.
Calculating the difference between 2 images. Since this is a small project, all input images will be of the same dpi and resolution and hence, once aligned, the difference between the input and the true images can give a rough estimate.
Which method do you think is the most viable?
It seems you are further advanced than you looked (seeing you comments) which is good! Im going to show you more or less the way you can go to solve you problem, however im not posting the whole code, just the important parts.
You have an image quite cropped and segmented. First you need to ensure that your image is without holes. So fill them!
Iinv=I==0; % you want 1 in money, 0 in not-money;
Ifill=imfill(Iinv,8,'holes'); % Fill holes
After that, you want to get only the boundary of the image:
Iedge=edge(Ifill);
And in the end you want to get the corners of that square:
C=corner(Iedge);
Now that you have 4 corners, you should be able to know the angle of this rotated "square". Once you get it do:
Irotate=imrotate(Icroped,angle);
Once here you may want to crop it again to end up just with the money! (aaah money always as an objective!)
Hope this helps!