Why draw a line don't produce a line with exact line thickness?

I’ve notice that drawing a line does not produce a line with the exact thickness. For example a line thickness of 15px draw a line with exactly 17 px of thickness, why is that?

See the following example:

line(img, pt1, pt2, color, thickness)

Thickness of 1px = Line of 1px
Thickness of 2px = Line of 3px
Thickness of 3px = Line of 4px
Thickness of 4px = Line of 5px
Thickness of 5px = Line of 7px
Thickness of 6px = Line of 7px
Thickness of 7px = Line of 9px
Thickness of 8px = Line of 9px
Thickness of 9px = Line of 11px
Thickness of 10px = Line of 11px
Thickness of 15px = Line of 17px
Thickness of 100px = Line of 101px
Thickness of 150px = Line of 151px

It seens there are from 1px to 2px error after 1px of thickness, why and how to counter this?

Additionally it creates a rounded start/end expanding it length, now to get rid of round ends and ensure exact length? (Without use a rectangle, i must be able to draw between two points on diferent XY on both ends)

1 Like

OpenCV’s drawing functions are weird.

  • cv.line uses repeated bresenham to draw thick lines, which is not pixel-accurate
  • cv.circle, for small circles, is particularly ugly. rounding issues.
  • using LINE_AA anywhere causes lines to be thicker than specified, and fuzzy even when the thickness is an odd integer and the line is axis-aligned and on the pixel grid.
  • findContours walks on top of the pixels that form the boundaries, rather than on the actual boundaries, because someone decided it has to roundtrip with drawContours/polygon drawing calls

I’ve tried to file an issue before that was left unaddressed, with comments suggesting that they don’t see it as an issue. maybe I hadn’t been clear enough.

you could try that. maybe you have better luck.

they probably just want someone who’s willing to dig into the code and fix it… but beware, it’s complicated code, because of optimization… that I don’t particularly notice, to be honest.

1 Like

Do you have the link of the issue?
Maybe we need a new function since that would change the current line that is used with a ton of programs. We may need a new function like: lineAccurate and pass a extra LineEndings enum with (Flat, FlatOutter, RoundInner, RoundOutter)
The problem is that thickness issue is present in every function that has a thickness parameter, like drawContours and others

I also have tried with an rotated rect but it will not always work, depending on XY1 and XY2 (my math is not the best):

public static void DrawStraightLine(this Mat src, Point pt1, Point pt2, MCvScalar color, int thickness, LineType lineType = LineType.EightConnected)
    {
        var deltaX = pt2.X - pt1.X;
        var deltaY = pt2.Y - pt1.Y;
        var deg = Math.Atan2(deltaY, deltaX) * (180 / Math.PI); 
        src.DrawRotatedRectangle(
            new Size(Math.Abs(deltaX), thickness), 
            new Point(pt1.X + deltaX / 2, pt1.Y + deltaY / 2), 
            color, (int)deg, -1, lineType);
    }

don’t worry, these APIs aren’t “nailed down” in ways that would require inventing new names. they can just be fixed, and suddenly everybody gets to enjoy exact drawing.

they just need to be fixed. the drawing primitives at least. contours are another mess entirely.

there is a lot to discuss. one issue is subpixel behavior. 1-thick lines ought to sit on pixels, but 2-sized lines… should straddle a pixel boundary and span exactly 2 pixels… but that’s just for speed/crispness. for accuracy (let’s say LINE_AA), a 2-width line should sit precisely where commanded, and cause 3 pixels to be painted. the center one completely, the adjacent two at 50%. I’d also want an option for roughly alpha-correct blending with alpha 2.2 or 2.4 (or a built-in LUT).

I don’t currently care about cap/join styles. seems okay to handle that with flags.

you can be sure that the rectangle call also just draws lines, so any issue with cv::line will replicate in all other drawing calls, e.g. circle (because that’s drawn as segments) and putText too because that’s using vector fonts!

here’s the issue I made a while ago. ignore my confusion about 4/8-connectivity. perhaps that’s why I didn’t manage to be understood.

1 Like

I know that openCV is flood with issues but maybe it require a new issue to explain the problem with more clear evidence that can’t be refused? Even I read you issue and find it confusing to understand the scope of the problem. And unfortunately old issues are forgotten and not touch anymore… I always found the draw functions lacking, some other libraries are mile ahead in this department, i know it’s not thier main focus but they can merge the best of both worlds

sure, try a new issue. a better writeup would help. I’d recommend closing my old one as duplicate then.