How to push a first whites (which is not equal to 0) elements from the mask image into the vector array to make line over stored points.

2 views (last 30 days)
I have scanned my image horizontally and vertically store the first white elements to a vector. And I want to create a vector which will store the first white elements. After storing the points draw line (as shown in the attached figure) over it.
I have already writen a code in C++, but I don't know how to write it in Matlab.
Here I attach a mask image from where i want to extract the while pixels (First white). For clarifications I have pointed out- what does first whites means in the mask image. Any help is much appreciated to achieve my target.
Hope this is clear.
// C++ code with openCV is shown below:
std::vector<int> firstWhite; // std::vector is a sequence container that encapsulates dynamic size arrays
for(int i=0; i<80; i++)
{
for(int j=0; j<img.rows; j++)
{
if(mask.at<uchar>(cv::Point(i,j)) != 0)
{
firstWhite.push_back(j);
j = 10000; // for example I have 10000 points in the mask image. I need quite fast access to every point.It is much more efficient to allocate too much memory than letting an array grow.
}
}
}
cv::line(img,cv::Point(0,firstWhite[0]),cv::Point(79,firstWhite[79]),cv::Scalar(0,0,0),2 );
// Converting C++ code to matlab. Below is my trial attemp. But unable to achieve the task.
[columns, rows, plane]=size(maskimage);
firstWhite=[]
for i=1: 80
for j=1:rows
if not(maskimage(i,j)==0)
firstWhite(end+1)=j
end
end
end
  5 Comments
KSSV
KSSV on 17 Jun 2021
Attach the original image.
You can get white pixels using:
I = imread('image.png') ;
I = imcrop(I) ; % pick only the required part of image
I1 = rgb2gray(I) ;
I2 = imbinarize(I1) ;
[y,x] = find(I2) ;
imshow(I)
hold on
plot(x,y,'.r')
kanika bhalla
kanika bhalla on 17 Jun 2021
Thank you so much for your reply @KSSV.
But I want to extract only first whites from the image (as showed in the image for reference). I had tried this [y,x] = find(I2); earlier. This is returning all whites present in the image.
As my task is to draw line over an image. Therefore, I am focused on finding first whites instead of all whites. Another constraint is that all process should be automatic. All process should be automatic. Even I tried in C++ but I don't know how to achieve that task in matlab. I have also attached the code in this post.
Can you please further guide me on this.
Here I attach an original image for your reference.
Many thanks for your help!!

Sign in to comment.

Accepted Answer

Walter Roberson
Walter Roberson on 17 Jun 2021
iminarize(), bwareafilt()
After that if your binary image is BW, then
first_white_row_idx = sum(cumprod(~BW,1)) + 1
but be careful: rows that have no white at all will show up with output one more than the number of rows
The code above is a vectorized way of find() of the first non-zero pixel for each column. Black is turned to 1's, cumprod that so that the leading 1's on a column are kept but the first 0 stops the run, sum; that gives you the number of 1's before the first 0, which is by construction the number of black pixels before the first white pixel. Add 1 to get the index of the first white pixel.
  9 Comments
Walter Roberson
Walter Roberson on 18 Jun 2021
filename = 'https://www.mathworks.com/matlabcentral/answers/uploaded_files/656085/image.jpeg';
Input_Originalimage = imread(filename); % Step 1: give original image as an input
Crop_image = imcrop(Input_Originalimage,[360 270 306 185]); % Step 2: Crop the original image
imshow(Crop_image)
[height, width, plane] = size(Crop_image);
R= Crop_image(:,:,1); % take the red channel of Crop_image
G=Crop_image(:,:,2); % take the green channel of Crop_image
B=Crop_image(:,:,3); % take the blue channel of Crop_image
mask = R > 130 & R < 150 & G > 150 & G < 180 & B > 110 & B < 150;
mask = bwareafilt(mask, [50 inf]);
figure; imshow(mask); % this is how I calculated a mask image
firstWhite = zeros(1,width);
for col = 1 : width
fw = find(mask(:,col),1);
if isempty(fw)
firstWhite(col) = nan;
else
firstWhite(col) = fw;
end
end
hold on
plot(firstWhite, 'y', 'linewidth', 2);
figure;
dfw = diff(firstWhite);
plot(dfw)
title('difference in firstWhite')
left_edge_x = find(dfw > 3, 1);
left_edge_y = firstWhite(left_edge_x);
right_edge_x = find(dfw < -3, 1, 'last')+1;
right_edge_y = firstWhite(right_edge_x);
figure
imshow(mask)
hold on
plot(firstWhite, 'y', 'linewidth', 2);
plot([left_edge_x, right_edge_x], [left_edge_y, right_edge_y], 'color', [1 .5 0], 'linewidth', 2)
kanika bhalla
kanika bhalla on 18 Jun 2021
I am indebted to your kindness and knowledge. I don't know of I'll ever be able to repay you properly. I am forever grateful to you Sir @Walter Roberson.
Next task is to find the first whites from the bottom to draw a line. I am trying best to implement the same according to your provided knowledge and solutions.
Thank you so much for your valuable time and support.

Sign in to comment.

More Answers (0)

Categories

Find more on Image Processing and Computer Vision in Help Center and File Exchange

Products


Release

R2019a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!