microsoft / Win2D

Win2D is an easy-to-use Windows Runtime API for immediate mode 2D graphics rendering with GPU acceleration. It is available to C#, C++ and VB developers writing apps for the Windows Universal Platform (UWP). It utilizes the power of Direct2D, and integrates seamlessly with XAML and CoreWindow.
http://microsoft.github.io/Win2D
Other
1.82k stars 287 forks source link

Question: Get Geometry from Bitmap alpha channel #193

Closed ChuckBerg closed 8 years ago

ChuckBerg commented 8 years ago

I'm looking for a method to obtain a CanvasGeometry object from the outline of a bitmap, where the outline is defined by non-zero alpha channel. Does such a capability already exist?

clandrew commented 8 years ago

There isn't a way to achieve this in Win2D- it's a very hard problem to solve, impossible to get right 100% of the time, and requires a bunch of knobs in order to be useful. For example- how to treat semitransparent alpha, how to treat different color channels, how much to simplify curves and jagged edges of the output geometry. Externally, there are some tools that attempt to do this type of conversion and expose these knobs as options. One example is Vector Magic.

Out of interest- what type of scenario do you have, where you need to convert raster data to geometry?

ChuckBerg commented 8 years ago

To clarify, I'm only looking for the outline of a the bitmap, not a full raster to vector conversion. The scenario is creating a path to drive an automatic cutting machine.

clandrew commented 8 years ago

That sounds like an interesting scenario!

In Win2D, a CanvasGeometry exclusively stores vector data. So producing a CanvasGeometry from an (raster) alpha mask will necessarily require a vector conversion.

ChuckBerg commented 8 years ago

True, a vector conversion is required. But not one that differentiates a person's face from hair. I can process an image to high contrast B&W and work with that to determine a vector definition of the outline.

clandrew commented 8 years ago

A high contrast black&white image definitely makes such a vectorization routine easier to get right. Moreover, your app may know something about the shape of the image (for example- lots of straight lines, or no overlapping contours) and be able to exploit that information.

Knowing this, while the feature doesn't exist in Win2D or Direct2D, it may be something well-suited to implement in your app. CanvasBitmap has a GetPixelColors, exposing the pixels that comprise the bitmap. CanvasGeometry has a CreatePath, allowing you to construct a geometry from arbitrary path points. With these pieces put together, your app could perform some analysis on the mask and produce the geometry. Due to the assumptions it can make about the source image, an app may be able to do a better job of this than a general-purpose tool.

clandrew commented 8 years ago

I'm going to close this issue, since this is not a feature we can add in Win2D and it doesn't look like there's anything for us to do. But, feel free to re-open if you need anything more here.

ChuckBerg commented 8 years ago

OK, I've created a path that "works" by adding 1 pixel length lines to PathBuilder. To improve transform performance, I would like to coalesce multiple co-linear lines into a single line. Will CanvasGeometry.Simplify() or CanvasGeometry.Outline() do that for me?

clandrew commented 8 years ago

Simplify and Outline don't coalesce co-linear lines. One reason there isn't a built-in way to do this, is that the geometry operations avoid things that require a compare for exact floating-point equality. It's prone to lots of problems unless there is some kind of knob (for example, a flatting tolerance) for it.

This is another thing the app could more reliably do, though- coalesce the co-linear lines while forming the path, comparing normalized line segments with floating point equality or equality-with-some-tolerance, and the app can decide what that tolerance is.

As a debugging aid, or if you want your app to do coalescing in a separate step, you can examine path data by implementing ICanvasPathReceiver and then send the path to it.

ChuckBerg commented 8 years ago

Out of curiosity then, what do Simplify and Outline do?

Sent from my Windows Phone


From: ClAndrewmailto:notifications@github.com Sent: ‎12/‎6/‎2015 1:12 PM To: Microsoft/Win2Dmailto:Win2D@noreply.github.com Cc: Chuck Bergmailto:ChuckBerg@charlesrberg.com Subject: Re: [Win2D] Question: Get Geometry from Bitmap alpha channel (#193)

Simplify and Outline don't coalesce co-linear lines. One reason there isn't a built-in way to do this, is that the geometry operations avoid things that require a compare for exact floating-point equality. It's prone to lots of problems unless there is some kind of knob (for example, a flatting tolerance) for it.

This is another thing the app could more reliably do, though- coalesce the co-linear lines while forming the path, comparing normalized line segments with floating point equality or equality-with-some-tolerance, and the app can decide what that tolerance is.

As a debugging aid, or if you want your app to do coalescing in a separate step, you can examine path data by implementing ICanvasPathReceiverhttp://microsoft.github.io/Win2D/html/T_Microsoft_Graphics_Canvas_Geometry_ICanvasPathReceiver.htm and then send the path to ithttp://microsoft.github.io/Win2D/html/M_Microsoft_Graphics_Canvas_Geometry_CanvasGeometry_SendPathTo.htm.

— Reply to this email directly or view it on GitHubhttps://github.com/Microsoft/Win2D/issues/193#issuecomment-162347937.

clandrew commented 8 years ago

Simplify has two modes. One of them lets you take any quadratics or arcs in the path, and turn them into cubics beziers only. The other mode strips out all curves, approximating them with (usually lots of small, short) line segments.

Outline removes all self-intersecting parts of a geometry.

There's some more specifics in our docs and the Direct2D docs.