how to create a region of interest in simulink

2 views (last 30 days)
I am trying to count the number of railroad ties in a video using simulink. The thought is to use sobel edge detection on each video frame. The railroad tie ends up being the background in the binary. Then use bottom-hat to apply a mask to the tie with an area say 15 pixels tall by 60 pixels wide. Then when the complete mask is in the region of interest it detects and counts the tie.
Attached is a frame from the video. I would like to create a rectangular region of interest x1=110, y1=105, x2=110, y2=75, x3=210, y3=75, x4=210, y4=105.
Does anyone know how to create a region of interest? I have looked at the examples in Matlab and I can't seem to figure it out.
Also, I am very new to Matlab/Simulink and not a computer scientist, vision/image scientist. So, if anyone has other suggestions I am very open to suggestions or if anyone thinks what I am doing can't be accomplished through this process then I am all ears as well.
Thanks

Accepted Answer

Sean de Wolski
Sean de Wolski on 26 Nov 2013
Edited: Sean de Wolski on 26 Nov 2013
If you have the Computer Vision System Toolbox then most of the functionality described by ImageAnalyst is available in Simulink blocks.
Alternatively you could do what he recommended by writing the code in MATLAB and then putting this in a MATLAB Function Block or an Interpreted function block if some of the code is not supported for code generation.
For this reason, I would recommend sticking with the CVST blocks:
more
Also, I would take a different approach than IA (live dangerously!). I would identify the right track using the same approach he did but then count the number of ties by identifying the rectangles with the bolts next to the right track and summing up the number of these rectangles.
  13 Comments
Kean
Kean on 2 Dec 2013
Sean...please see attached
I made some changes. Tell me what you think b/c I am still trying to understand the logic/processes. Here is my understanding of the way it works: Open avi -> change from RGB to intensity -> crop the frame so it only looks between the rails -> use stdfilt() to find standard deviation -> set the threshold to "find" locations and mark 0 or 1 -> mask the found locations -> sum across the rows -> if between rows 0 and 45 there is a mask then count 1 -> sum all counts
Sean de Wolski
Sean de Wolski on 2 Dec 2013
Close!
  1. read image in, convert to grayscale double
  2. stdfilt to identify areas of low standard deviation within a 9x9 neighborhood (i.e. the compare to 5). This indicates tracks. All numbers were chosen by trial + error
  3. dilate horizontally (rectangle [1x50]) because tracks are horizontal
  4. erode vertically to remove noise between tracks
  5. Sum each row (recieve a column vector)
  6. if there are more than 100 true pixels in a row, it's a track (wooohoo!)
  7. Only look at the first row (selector)
  8. Identify when the first row goes from being a zero to a one (difference - compare to one).
  9. Use the StopCallback to sum up how many ones there are, i.e. the total number of tracks and put this in the workspace as NTies.

Sign in to comment.

More Answers (2)

Image Analyst
Image Analyst on 26 Nov 2013
I don't know how to do it in Simulink, but if you can write custom MATLAB code in a Simulink block, what I'd do it first sum the image vertically and detect the two rails. Then get rid of those columns - remove them from the image. Then so some sort of texture filter such as stdfilt() or imgradient() to get a texture image. Then sum that horizontally. High sum regions will be gravel/rocks. Low sum regions will be railroad ties. Then just threshold and pass the binary vector into bwlabel to count the ties, or pass into regionprops if you want to determine how many ties and fractions of ties there are. Not too hard. Can you code that up? If not let me know and I'll help you.
  21 Comments
Kean
Kean on 27 Nov 2013
It's a bit more tricky than counting when it goes from 1 to 0. Because it would be scanning every frame and making duplicates. Would it be possible to detect the 1 to 0 between say rows 30 to 70 and when it rises between rows 30 to 70 it counts a tie. Then make the same detection again between those rows? I am I thinking about this right?
Kean
Kean on 1 Dec 2013
IA i am stumped on how to proceed further. Can you offer up any more hints? thanks.

Sign in to comment.


Kean
Kean on 3 Dec 2013
Sean...in step 6 is there a way to look at the sum of say 10 rows such that if the total was 1000 it would "detect" the tie?
  4 Comments
Sean de Wolski
Sean de Wolski on 3 Dec 2013
Use a selector block to "select" the first 10 elements in the signal before the sum block
Kean
Kean on 4 Dec 2013
Sean...attached is what I have come up with. Not sure if it is doing what I intended by summing the column vector for the first "n" rows then if above a constant return 1. It just doesn't seem to be as sensitive to the that constant. I am getting the correct count of 209. I like your idea of cleaning up the signal using the dialate/erode but I wanted to try something different. Would you mind taking a quick look if I have the logic correct?

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!