-2

I'm need to detect lines by drawing a line across the lines :)

The number of lines are unknown and differs from image to image. The direction of the lines can also differ. But for my example below I have six vertical lines.

I then want to draw a line across the six lines and my drawn line should detect the lines and also pinpoint the found line by adding a circle in a color. The goal is to receive an int with the lines found so I can continue doing calculations.

I have an Image encapsuled within a canvas.

<Canvas x:Name="Cnv" Width="640" Height="480"
            PreviewMouseUp="Image_MouseLeftButtonUp"
            PreviewMouseMove="MapImg_MouseMove">
        <Image x:Name="MapImg" Width="640" Height="480" Source="/images/test.png"/>
</Canvas>

I've managed to create the function so I can draw a line but I've searched quite a lot trying to find a solution for the detection. I successfully detected shapes with AForge framework but that was for a whole image from my understanding.

Very grateful for you help if possible.

EDIT: The line that should detect the lines are drawn and the other lines comes from an image / bitmap. Is there anything that might detect the lines by contrast (detecting the white)?

EDIT 2: Replace the picture with a more accurate image trying to explain.

enter image description here

Znyder
  • 51
  • 7
  • @Clemens: this is of little help. The lines are not given by equations. –  Feb 25 '22 at 15:25
  • "The direction of the lines can also differ": example, please. –  Feb 25 '22 at 15:31
  • The lines that I want to detect can be horizontal or vertical or anything inbetween, it depends on the rotation of the image. But the line I want to draw could be drawn however by the user, but I want to detect the lines that crosses the drawn line. I was wondering if this could be done by detecting the contrast somehow? By measuring values of "white" or something.. – Znyder Feb 25 '22 at 15:37
  • You do not really need to use any third party library for a fairly simple task like this, at least as long as the image is sharp and has little noise. But you will probably need some basic knowledge on how to work with images. – JonasH Feb 25 '22 at 15:45
  • JonasH: Could you please redirect me to where to start reading? The image is sharp with no noise. I just wonder if I should start reading about image processing but would just need some help on what... :) – Znyder Feb 25 '22 at 15:50

1 Answers1

2

To provide a somewhat high level overview of such a solution.

To start of you need access to the pixel-Values, how this is done depends on the type of image you have. For a bitmapSource the recommended way seem to be to use CopyPixels.

Then you need to process each pixel along the line. The simplest way to do this would be to convert the line to a start position and a normalized direction and use this to sample along the line. Assuming pixel coordinates, something like:

for(var d = 0; d < myLine.Length ; d++){
    var samplePos = myLine.StartPosition + myLine.Direction * d;
    ...
}

This sample position can then be used to extract the value for that pixel, I will assume that the image is grayscale, otherwise you might want to convert the color value. This very simple method might sample a pixel multiple times, but that should not be a problem. You can then use a threshold value to determine if a pixel is part of a line or not. Once you have found a pixel value large enough you would save that position, and the next time you find a low value you can average the positions and return it as the center point of a line. I.e. you would find the transitions between "black" and "white", and average pairs of two such transitions.

Something like this pseudo code:

int previousValue = 0;
Point startPos ;
for(var d = 0; d < myLine.Length ; d++){
    var samplePos = myLine.StartPosition + myLine.Direction * d;
    var pixelValue = myImage[samplePos];
    if(pixelValue > myThreshold && previousValue < myThreshold){
        startPos = samplePos;
    }
    if( pixelValue < myThreshold && previousValue > myThreshold){
        yield return (startPos + samplePos)/2;
    }    
    previousValue = pixelValue;
}

This leaves out details like how to sample a pixel value at some specific position, and that you have suitable classes to work with pixel coordinates and directions etc. It also assumes the first pixel will always be black, if that is not the case you might need some special handling depending on what you want to do.

This should work well for cases like a binary image. More advanced algorithms might be faster and/or handle problematic cases better.

JonasH
  • 28,608
  • 2
  • 10
  • 23
  • Thank you JonasH! Just what I needed. I'm not there yet but I've managed to retrieve the points from the line I've drawn. I will continue and retrieve the pixel value from the bitmap with these points. Thank you again pointing me in the right direction :) – Znyder Feb 26 '22 at 07:38