remove some top, down rows and right, and left some columns of jpg image border using matlab - matlab

I have RGB museum JPG Images. most of them have image footnotes on one or more sides, and I'd like to remove them. I do that manually using paint software. now I applied the following matlab code to remove the image footnotes automatically. I get a good result for some images but for others it not remove any border. Please, can any one help me by update this code to apply it for all images?
'rgbIm = im2double(imread('A3.JPG'));
hsv=rgb2hsv(rgbIm);
m = hsv(:,:,2);
foreground = m > 0.06; % value of background
foreground = bwareaopen(foreground, 1000); % or whatever.
labeledImage = bwlabel(foreground);
measurements = regionprops(labeledImage, 'BoundingBox');
ww = measurements.BoundingBox;
croppedImage = imcrop(rgbImage, ww);'

In order to remove the boundaries you could use "imclearborder", where it checks for labelled components at boundaries and clears them. Caution! if the ROI touches the boundary, it may remove. To avoid such instance you can use "imerode" with desired "strel" -( a line or disc) before clearing the borders. The accuracy or generalizing the method to work for all images depends entirely on "threshold" which separates the foreground and background.
More generic method could be - try to extract the properties of footnotes. For instance, If they are just some texts, you can easily remove them by using a edge detection and morphology opening with line structuring element along the cols. (basic property for text detection)
Hope it helps.
I could give you a clear idea or method if you upload the image.

Related

Filling the gaps in a binary image

I have found a couple areas referring to filling of gaps in binary images in matlab, however I am still struggling. I have written the following code but I cannot get it to work. Here is my binary image:
.
However, what I'm trying to achieve is the following
.
Does anyone know how to do this? I have been trying using imfill but I know I think I need to define boundaries also with the bwlabel function but I dont know how. Any help would be greatly appreciated.
%%Blade_Image_Processing
clc;
clear;
%%Video file information
obj = VideoReader('T9_720p;60p_60mm_f4.MOV');
% Sampling rate - Frames per second
fps = get(obj, 'FrameRate');
dt = 1/fps;
% ----- find image info -----
file_info = get(obj);
image_width = file_info.Width;
image_height = file_info.Height;
% Desired image size
x_range = 1:image_height;
y_range = 1:image_width;
szx = length(x_range);
szy = length(y_range);
%%Get grayscale image
grayscaleimg1 = rgb2gray(read(obj,36));
grayscaleimg = imadjust(grayscaleimg1);
diff_im = medfilt2(grayscaleimg, [3 3]);
t1=60;
t2=170;
range=(diff_im > t1 & diff_im <= t2);
diff_im (range)=255;
diff_im (~range)=0;
% Remove all those pixels less than 300px
diff_im = bwareaopen(diff_im,2000);
%imshow(diff_im)
%imhist(grayscaleimg)
%Fill gaps in binary image
BW2 = imfill(diff_im,'holes');
There are two main problems: desired object has no readily usable distinguishing features, and it touches other object. Second problem could be perhaps cleared with morphological opening/closing (touching object is thin, desired object not, is this always the case?), but first problem remains. If your object touched edge but others didn't or vice versa, you could do something with imfill and subtractions. As it is now, MAYBE something like this would work:
With opening/closing remove connection, so your object is disjoint.
With imfill, remove what is left of this thin horizontal thing.
Then, you can bwlabel and remove everything that touches sides or bottom of the image - in shown case that would leave only your object.
Exact solution depends heavily on what additional constrains are there for your pictures. I believe it is not a one-shot, rather you have more of those pictures and want to correctly find objects on all? You have to check what holds for all pictures, such as if object always touches only something thin or if it always touches only upper edge etc.

Dilate an image based on a distribution

I have an image that show some random filled circles (e.g. see here). I want to change these circles to make some irregular shapes. In other words, I want to define a distribution by which I can expand the circles. Clearly, the resulted new objects will not be circles anymore, because the generated objects are expanded based on a distribution which is variable; see this new deformed circle.
I was wondering if there is any method that can do this? In my first try, I tried to use image dilation in Matlab, but I have no idea on how the dilation "distribution" should be used.
IM2 = imdilate(IM,SE)
If you want to do it using dilation, a solution could be:
Let say Im is your original image
ImResult = Same(Im)
ImClone = Clone(Im)
Randomly delete pixels in ImClone. The number of pixels to delete may be a percentage, or whatever you prefer
ImDilate = Dilate(ImClone), with the structuring element of size N
Result = Maximum(Result, ImDilate)
If you want different size of deformations, then you iterate from step 3 to 6, with different structuring element sizes.
But what you want is more an elastic deformation. You should take a look to the free form deformation (FFD).

Remove noise close to an object of a grayscale image

I have the image bellow that has a main object and around it there is some noise, like smoke, circled with the red line.
Is it possible to remove this noise keeping the main object intact as possible?
Can we do that without using a manual threshold, e.g., look here if that helps?
I would like to mention that the background does not correspond to zero values. So applying a threshold method and setting to zero the corresponding spots, based on the obtained mask, will destroy the smoothness of the background.
Best regards,
Thoth
EDIT: Just for the visualization purposes, I placed an output image (I just copy a background patch inside the circle.)
S.A.
Yes you can simply accomplish your task using some morphological operations such as
Opening
Closing
Dilation
Erosion
and here is a simple code that may help you :
%After input image 'img' is read:
structuredElement1 = strel('disk',5);
structuredElement2 = strel('disk',3);
imageAfterErosion = imerode(img,structuredElement2);
imageAfterClosing = imclose(imageAfterErosion,structuredElement1);
imageAfterDilation = imdilate(imageAfterClosing,structuredElement1);
imageAfterDilation = imdilate(imageAfterDilation,structuredElement1);
imageAfterClosing = imclose(imageAfterDilation,structuredElement1);
binaryImage = imfill(imageAfterClosing, 'holes');
imshow(binaryImage);

How can I replace the border with white color in Matlab?

This is the original image.
I changed it into 1) grayscale and apply 2) threshold.
As seen in the original image, there are some shadow that still exist after apply two method above.
But most of the image are perfect after 2 method.
I need to extract the text, so I need to get rid of the noise. I almost finish the work but the problem is some cases have a black border and I wanted to replace that into white color.
And I insist that I want just only border to turn into white
I think of create some white rectangle and fill the border with those rectangle but I don't know how to do it.
How can I achieve that using Matlab?
Any other method would be appreciate too!
If you can be sure only the borders will be black, why not simply crop the image until all isolated shapes are recognizable characters? Something along the lines of
done = false;
ii = 1;
while (~done)
% fill the outer border
img(:,ii) = 255; img(ii,:) = 255;
img(:,end-ii+1) = 255; img(end-ii+1,:) = 255;
% (run your algorithms here. It positive match, done = true)
end
That could be computationally intensive, since you have to do pattern recognition on each iteration, but you indicated it only occurs in "some cases".
Otherwise, I suspect some morphological operation can also be used, probably erosion or thinning or similar. But that has the drawback of altering the characters you want to match. But, if all images you have to process look like the one you show, I hardly suspect that'll give you any problems.
Some ways to detecting straight lines are mentioned in this question. I'd say you could detect all lines, and remove those (with a small tolerance around it) that are perfectly horizontal/vertical and on one of the edges.

Lock image size on Matlab GUI

I'm making a GUI in MatLab that asks the user to upload a video file.
Next I want to play it in axes with a fixed window size . However, if the uploaded file is large, Matlab will expand the axes and take over most of my GUI. Is there a way to shrink the image to make it fit the axes?
Does anyone know how to solve this?
Usually Matlab axes are not supposed to change their position if the image is too big.
I can think of two possible problems:
The axes were large from the beginning, but showed small image with margins if the image is small enough
The command of showing the image that you are using is custom and it changes the axes size.
This question is old, but I stumbled across this (looking for something else) so perhaps it will help someone to see what I did.
I wanted to resize pretty large images (1024x 100k-200k pixels) so that my GUI can quickly demonstrate various color operations on a view of these large data sets. I just manually sub-sampled my data as follows (functions below).
Note that this example is an image. To spatially sub-sample a video, I have looped through the video and done something similar in the past on each frame.
[plotWidthPixels, plotHeightPixels] = getPlotAreaPixels(handles.figure1, handles.axes1);
[nSamplesPerLine nLines] = size(iqData);
colInds = decimateToNumber(nLines,plotWidthPixels);
rowInds = decimateToNumber(nSamplesPerLine,plotHeightPixels);
iqDataToPlot = iqData(rowInds,colInds);
First, I got the axis size in pixels:
function [plotWidthPixels, plotHeightPixels] = getPlotAreaPixels(figHandle, axisHandle)
set(figHandle,'Units','pixels')
figSizePix = get(figHandle,'Position');
set(axisHandle,'Units','normalized')
axSizeNorm = get(axisHandle,'Position');
axisSizePix = figSizePix.*axSizeNorm;
plotWidthPixels = ceil(axisSizePix(3)-axisSizePix(1));
plotHeightPixels = ceil(axisSizePix(4)-axisSizePix(2));
Then I used that to decimate the width and height of my image by getting sub-sets of indices that are (crudely approximately) evenly spaced:
function inds = decimateToNumber(lengthOfInitialVector, desiredVectorLength, initialIndex)
if nargin < 3
initialIndex = 1;
end
if (lengthOfInitialVector-initialIndex+1) > desiredVectorLength*2
inds = round(linspace(initialIndex,lengthOfInitialVector,desiredVectorLength));
else
inds = initialIndex:lengthOfInitialVector;
end