How to process only a select area of an image help!?
23 views (last 30 days)
Show older comments
Hi everybody,
So, I have made a bit of code that processes an image but I have had an idea which means now I only need to process a small part of the image. I have taken a picture, and made the image black and white. The white bit (A strip of paper near the middle of the picture) is the area of interest that needs the main code running on it. I have also made code that finds the very top left of the white area so I know the pixel values (x,y) of it. What I want to do is urn my main code on an area 350 x 450 pixels starting at these x,y coordinates BUT these pixel values can change qith each picture I use. To try and combat this I assigned the pixel value numbers the letters 'x' and 'y' and used 'imcrop' but it has failed to work. Below is my code, so any ideas will help :) I hope looking at my code will help explain what I'm trying to do. Ive found the top left pixel values of an area of interest. I want to crop the image to 350 x 450 rectangle starting at them pixels and then process only on that area! Thankyou very much. Here is my code (line with %%%%%% at the end is the issue):
RGB = imread('IMG_1765.JPG');
Binary_Image = imread('IMG_1765 (2).JPG');
% Convert RGB image to chosen color space
Original_Picture = RGB;
% Define thresholds for channel 1 based on histogram settings
channel1Min = 149.000;
channel1Max = 255.000;
% Define thresholds for channel 2 based on histogram settings
channel2Min = 140.000;
channel2Max = 255.000;
% Define thresholds for channel 3 based on histogram settings
channel3Min = 140.000;
channel3Max = 255.000;
% Create mask based on chosen histogram thresholds
BW = (Original_Picture(:,:,1) >= channel1Min ) & (Original_Picture(:,:,1) <= channel1Max) & ...
(Original_Picture(:,:,2) >= channel2Min ) & (Original_Picture(:,:,2) <= channel2Max) & ...
(Original_Picture(:,:,3) >= channel3Min ) & (Original_Picture(:,:,3) <= channel3Max);
% Initialize output masked image based on input image.
maskedRGBImage_2 = RGB;
% Set background pixels where BW is false to zero.
maskedRGBImage_2(repmat(~BW,[1 1 3])) = 0;
%AFTER PAPER IS FOUND AND THRESHOLDED TO WHITE, THE FOLLOWING CODE LOCATES
%AREA OF INTEREST
Image_Size=size(Binary_Image);
x = Image_Size(2);
y = Image_Size(1);
s = zeros(1,350); %Array of test pixels
top_left_x = 0;
top_left_y = 0;
for y = 1:3168;
for x = 1:4752;
Test_pixel = Binary_Image(y,x);
if Test_pixel == 255
for k = x:(x+349);
%Generates value of test pixel
g = Binary_Image(y, k);
%Populates array of test pixels
f = k - x + 1;
s(1,f) = g;
g_sum = nnz(s);
if g_sum > 330; %This is 0.95*white line so 330/350 pixels are white
top_left_x = x;
top_left_y = y;
return
end
end
end
end
end
%Now we can crop the original image using the pixel values found in the
%above loop
% Convert RGB image to chosen color space. Cropped based on original normal
% test pics
Original_Picture = imcrop(rgb2hsv(RGB),[x y (x+350)-x (y+450)-y]); %%%%%%
% Define thresholds for channel 1 based on histogram settings
channel1Min = 0.063;
channel1Max = 0.096;
% Define thresholds for channel 2 based on histogram settings
channel2Min = 0.111;
channel2Max = 0.131;
% Define thresholds for channel 3 based on histogram settings
channel3Min = 0.612;
channel3Max = 0.647;
% Create mask based on chosen histogram thresholds
BW = (Original_Picture(:,:,1) >= channel1Min ) & (Original_Picture(:,:,1) <= channel1Max) & ...
(Original_Picture(:,:,2) >= channel2Min ) & (Original_Picture(:,:,2) <= channel2Max) & ...
(Original_Picture(:,:,3) >= channel3Min ) & (Original_Picture(:,:,3) <= channel3Max);
% Invert mask
BW = ~BW;
% Initialize output masked image based on input image.
maskedRGBImage_2 = RGB;
% Set background pixels where BW is false to zero.
maskedRGBImage_2(repmat(~BW,[1 1 3])) = 0;
0 Comments
Answers (2)
Matt Cohen
on 16 May 2016
Hi Ellis,
I understand that you are trying to identify the top-left pixel location for a region and then use the IMCROP function to crop the image at this location.
Without the images, I am not able to exactly reproduce this issue. However, based on the code, it appears that you might be misusing certain variables and overwriting specific values. For instance, you initially store the width and height of the image in the 'x' and 'y' variables; you then overwrite these variables' values when you use them as the for loop index variables.
Inside the for loop, you are trying to determine the location in the image of the top-left corner of the sub-region. You store these location values in the 'top_left_x' and 'top_left_y' variables. However, you do not use these when cropping the image with IMCROP. Instead, you are using the 'x' and 'y' variables. Since these are the for loop index variables, they take on their final values from the for loop, which, in this case, should be 3168 for 'y' and 4752 for 'x'. These variables will always have these values, regardless of the image and the sub-region location found.
One thing that might fix your issue is to use the following code for cropping the image:
Original_Picture = imcrop(rgb2hsv(RGB),[top_left_x top_left_y 350 450]); %%%%%%
This will make use of the top-left corner locations and should eliminate any errors you are encountering by not extending outside of the image when cropping. Again, without the images, I cannot test this to make sure it accurately accomplishes your desired task, but it should get you closer to the solution. Try out this change and play around with the ordering of 'top_left_x' and 'top_left_y' to make sure they have not been swapped.
I hope this helps.
Matt
0 Comments
Image Analyst
on 16 May 2016
What is the for loop supposed to do? You already have the binary image BW which is a segmented image of paper. So what do you want the for loop to do? It seems to build up "s" which never gets used. Then you also get the bounding box which you can get much, much simpler with regionprops()
[labeledImage, numRegions] = bwlabel(BW);
measurements = regionprops(labeledImage, 'BoundingBox');
If there is only 1 region, you can get the bounding box and mask like this:
boundingBox = measurements(1).BoundingBox;
croppedImage = imcrop(maskedRGBImage_2, boundingBox);
0 Comments
See Also
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!