<a id="easyimage-straight-line-detector"></a>

# Straight Line Detector

The **EasyImage** straight line detector finds straight line segments in a BW8 binary image. It uses the probabilistic Hough transform to vote for candidate lines, then merges nearby collinear segments. The result is a vector of [`ELine`](../../../doxygen_cpp/classeVision_1_1ELine.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ELine.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ELine.html) objects sorted from longest to shortest.

![](assets/images/easyimage/straight_line_detector_source.webp)![](assets/images/easyimage/straight_line_detector_result.webp)

The detector accepts a BW8 image, an optional region of interest, and an optional frame. You can also supply only a region, without an image.

<a id="easyimage-straight-line-detector-input-image"></a>

## Input Image

The input is not a grayscale image but a **binary BW8 image**: the white pixels (255) are the surface on which lines are searched, and the black pixels (0) are ignored. This image can be generated from:

* The [skeleton of an image](non-linear_filtering.html.md#easyimage-non-linear-filtering-thinning) with [`EasyImage::Thinning`](../../../doxygen_cpp/classeVision_1_1EasyImage.html#a699bf8dffe8276e34a47ce67142543f0) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyImage.html#a573cf7358f6127f81469ae7ad78d20af) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyImage.html#a7d8c4ef41c8f882a5d1b4516088607ee).
* The [edges of an image](canny_edge_detector.html.md#easyimage-canny-edge-detector) with [`ECannyEdgeDetector`](../../../doxygen_cpp/classeVision_1_1ECannyEdgeDetector.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ECannyEdgeDetector.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ECannyEdgeDetector.html).
* The [threshold of an image](thresholding.html.md#easyimage-thresholding) with [`EasyImage::Threshold`](../../../doxygen_cpp/classeVision_1_1EasyImage.html#ac6f69c1aac9510ac6cd639acb27979ee) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyImage.html#ae13e71e4c82873cb82b2b72bb9fb1b7e) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyImage.html#a0b095d913c4676c6c3be8f73e4c06dea).

#### NOTE
The objects of interest must be **white** on a black background. If they are black, invert the image first with [`EasyImage::Oper`](../../../doxygen_cpp/classeVision_1_1EasyImage.html#adf314c42c92233ca337668250125375e) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EasyImage.html#afcbccbf75626021b9a80ae1f9978eac4) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EasyImage.html#ad2662856c57834c7b067d0b4a957d097) and the [`EArithmeticLogicOperation_Invert`](../../../doxygen_cpp/namespaceeVision.html#aebf26b10397a83bd42f31e33b5d59d83) [<sub>Python</sub>](../../../doxygen_cs/namespaceeVision.html#a42668c67c44fbf0785f8d727ecf9963d) [<sub>.NET</sub>](../../../doxygen_python/classeVision_1_1EArithmeticLogicOperation.html) operation.

#### TIP
The detection time grows with the number of white pixels. Running the detector directly on large white blobs, such as a thresholded image, is slow. When possible, reduce the blobs to thin structures first with the Canny edge detector or with the thinning operation: the detected lines are the same, but the detection is much faster.

The input image can also be [denoised](noise_reduction_and_estimation.html.md#easyimage-noise-reduction) to improve the line detection.

<a id="easyimage-straight-line-detector-parameters"></a>

## Parameters

The detector uses two groups of parameters.

**Hough parameters** control the vote accumulator:

| Parameter   | Description                                                         | Default   |
|-------------|---------------------------------------------------------------------|-----------|
| `rho`       | Distance resolution of the accumulator, in pixels.                  | 1 px      |
| `theta`     | Angle resolution of the accumulator, in degrees.                    | 1°        |
| `threshold` | Minimum number of Hough votes for a candidate to qualify as a line. | 150       |

**Segment merging parameters** control how raw detections are joined into final line segments:

| Parameter        | Description                                                                                      | Default   |
|------------------|--------------------------------------------------------------------------------------------------|-----------|
| `minLineLength`  | Minimum length of a detected segment, in pixels. Shorter segments are discarded.                 | 64 px     |
| `maxLineGap`     | Maximum gap between two collinear segments for them to be merged into one.                       | 164 px    |
| `angleThreshold` | Maximum angular difference, in degrees, for two segments to be considered part of the same line. | 35°       |

<a id="easyimage-straight-line-detector-inputs"></a>

## Inputs

[`ELineDetector::Detect`](../../../doxygen_cpp/classeVision_1_1ELineDetector.html#a84fb6fd683b6fb9a92fea10018debc78) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ELineDetector.html#a096cd6458f6a7e9737288bfc5f0fcbd0) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ELineDetector.html#a213d88168d23e53ae2add65a48708255) accepts an image, an optional region, and an optional frame. Supply a region to restrict detection to a specific area of the image. Supply a region alone, without an image, to detect lines directly on the region’s shape.

Detected lines are always returned in the coordinate system of the frame when one is provided.

<a id="easyimage-straight-line-detector-output"></a>

## Output

All overloads return `std::vector<ELine>`. The lines are sorted by length in descending order: the longest detected line is always at index 0.

Each [`ELine`](../../../doxygen_cpp/classeVision_1_1ELine.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ELine.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ELine.html) carries:

- Start point and end point.
- Length.
- Angle.

<a id="easyimage-straight-line-detector-api"></a>

## API

The API of the straight line detector is the [`ELineDetector`](../../../doxygen_cpp/classeVision_1_1ELineDetector.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ELineDetector.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ELineDetector.html) class:

- [`ELineDetector::Detect`](../../../doxygen_cpp/classeVision_1_1ELineDetector.html#a84fb6fd683b6fb9a92fea10018debc78) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ELineDetector.html#a096cd6458f6a7e9737288bfc5f0fcbd0) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ELineDetector.html#a213d88168d23e53ae2add65a48708255): detects straight lines and returns them sorted by length.
- [`ELineDetector::SetRadialBinSize`](../../../doxygen_cpp/classeVision_1_1ELineDetector.html#ac31018bc29ccedb95d620a9d286b5424) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ELineDetector.html#ae3eb12cfb5c55225d5dac6c5bc9d8426) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ELineDetector.html#aa20cee2a0dea59fd3c063ad50184de44): sets the distance resolution of the accumulator.
- [`ELineDetector::SetAngularBinSize`](../../../doxygen_cpp/classeVision_1_1ELineDetector.html#a55033f1a81df246ca4473d923aa37a44) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ELineDetector.html#aa7345dfb04dfbb7a95c0a6ee7de1ae30) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ELineDetector.html#a4089ef732c61325662c458f60d3a4273): sets the angle resolution of the accumulator.
- [`ELineDetector::SetMinNumVotes`](../../../doxygen_cpp/classeVision_1_1ELineDetector.html#a540f27bbde1d34327df57deb1f5044c2) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ELineDetector.html#a5137ef419846ec5a92c5de0320571e4a) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ELineDetector.html#a66815f0ac4f202fafd40cf4cb94cc2cc): sets the minimum number of Hough votes.
- [`ELineDetector::SetMinLineLength`](../../../doxygen_cpp/classeVision_1_1ELineDetector.html#ae722a6af59c02609a1eae58fe7d88b3a) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ELineDetector.html#a236cf7d33edbc8862867be505c1775fc) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ELineDetector.html#a7da9b334646b47c002549ba516518aa1): sets the minimum line segment length.
- [`ELineDetector::SetMaxLineGap`](../../../doxygen_cpp/classeVision_1_1ELineDetector.html#a78e5210001ba4fd2a7827339e8c9c9dc) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ELineDetector.html#af9cbdc51f3a98137413d941364715bb7) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ELineDetector.html#a7dec51e869ba9ff08e80ec0ae60194f6): sets the maximum merging gap.
- [`ELineDetector::SetAngleThreshold`](../../../doxygen_cpp/classeVision_1_1ELineDetector.html#a0b016965b6463dfe1e33f757c4811566) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ELineDetector.html#acad8855e93c25a898dd57a58d194c80f) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ELineDetector.html#a915a4959a7022c685917c2f84c04ae67): sets the maximum angular difference for merging.
- [`ELineDetector::GetSegmentsBeforeMerging`](../../../doxygen_cpp/classeVision_1_1ELineDetector.html#afdf691928eb97312c25ba72ea97eec0d) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ELineDetector.html#a495af54794c8d620fa531d46eea1c396) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ELineDetector.html#a94f0165a73f3717d97d816ede7e3c0bf): returns the raw segments found by the last detection, before they were merged. See [Debugging the Detection]().
- [`ELineDetector::Save`](../../../doxygen_cpp/classeVision_1_1ELineDetector.html#ac78f500d76f36e6ac454b98036c6a259) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ELineDetector.html#a5a63009131c7251466dcb0788bb24710) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ELineDetector.html#a38667e15131941b855174031b59b1ba2): saves the detector configuration to a file.
- [`ELineDetector::Load`](../../../doxygen_cpp/classeVision_1_1ELineDetector.html#a445be2307b5779ac5c1ea48768beb108) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ELineDetector.html#a3abc665d6ea4c794d6c0eceefe42dfe2) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ELineDetector.html#a8eb59058fe34c13f2f77d647696ba36f): loads a detector configuration from a file.

<a id="easyimage-straight-line-detector-debugging"></a>

## Debugging the Detection

The final lines are built by merging raw segments, according to `maxLineGap` and `angleThreshold`. When a result is not what you expect (a line split in two, two distinct lines fused into one, a line missing), it is hard to tell whether the problem comes from the Hough detection or from the merging step.

[`ELineDetector::GetSegmentBeforeMerging`](../../../doxygen_cpp/classeVision_1_1ELineDetector.html#afdf691928eb97312c25ba72ea97eec0d) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ELineDetector.html#a495af54794c8d620fa531d46eea1c396) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ELineDetector.html#a94f0165a73f3717d97d816ede7e3c0bf) returns the raw segments found by the last call to [`ELineDetector::Detect`](../../../doxygen_cpp/classeVision_1_1ELineDetector.html#a84fb6fd683b6fb9a92fea10018debc78), **before** the merging step. Comparing them with the final lines shows what the merging did:

* If a raw segment is missing where you expect a line, the problem is upstream of the merging: adjust the Hough parameters (`threshold`, `rho`, `theta`), `minLineLength`, or improve the input image.
* If several raw segments lie on the same physical line but were not merged, increase `maxLineGap` or `angleThreshold`.
* If raw segments of different physical lines were fused, decrease `maxLineGap` or `angleThreshold`.

#### NOTE
* The segments are only available after a call to `Detect`, and are overwritten by the next call.
* The segments are expressed in the same coordinate system as the lines returned by `Detect`: the local frame when a frame is provided.
* The segments are returned in no particular order, and are not sorted by length.

### In eVision Studio

The **Line Detector** tool uses this method to display the raw segments on the image. After each detection, the tool retrieves the segments with `GetSegmentBeforeMerging` and draws them in its display.

In the setup view of the tool, open the **Display options** category of the property grid:

* **Show lines**: draws the final detected lines, in blue. The selected line is drawn in green.
* **Show segments before merging**: draws the raw segments returned by `GetSegmentsBeforeMerging`. Each segment is drawn with its own random colour, so that neighbouring segments can be told apart.

To debug a detection:

1. Enable **Show segments before merging**. Disable **Show lines** if the blue lines hide the segments.
2. Check that each expected line is covered by one or more raw segments. If not, adjust the Hough parameters or the minimum line length.
3. Look at how the segments group into lines. Adjust **Maximum gap** and the angle threshold in the merging parameters until the segments of a same line are merged, and the segments of different lines are not.
4. Re-enable **Show lines** to confirm the final result.

The same option is available in the view of the tool, as set from the setup.

<a id="easyimage-straight-line-detector-usage"></a>

## Basic Usage

1. **Create an [`ELineDetector`](../../../doxygen_cpp/classeVision_1_1ELineDetector.html) instance.** The default parameters work well for clear, long lines.
2. **Adjust parameters if needed.** Lower `threshold` or `minLineLength` to detect shorter or fainter lines. Increase `maxLineGap` to bridge gaps in broken lines.
3. **Call [`ELineDetector::Detect`](../../../doxygen_cpp/classeVision_1_1ELineDetector.html#a84fb6fd683b6fb9a92fea10018debc78)** with a [binary BW8 image](), and optionally a region and a frame.
4. **Iterate over the result vector.** The line at index 0 is the longest detected line.

#### SEE ALSO
* [Canny Edge Detector](canny_edge_detector.html.md): Detect edges in an image using gradient magnitudes and hysteresis thresholding..
* [Harris Corner Detector](harris_corner_detector.html.md): Detect corners and points of interest in an image.
