WPF中的每像素行进蚂蚁选择边界

时间:2016-01-30 21:32:23

标签: c# wpf

我发现了一些矩形行进蚂蚁选择方法,大多使用矩形,例如greater of the two上的这个矩形。使用形状和故事板可以使用。问题是我使用CodeProject: Marching Ants Selection比例布局变换控制image's缩放,这也会改变形状边框的大小。

但是,我希望能够创建每像素选择边框:

grid's

我目前的计划是存储一个包含代表当前所选像素的位掩码的位图,但我必须使用类似enter image description here的内容来遍历其周边,以构建代表边界的复合Marching Squares

不过,也许还有更好的方法吗?

以下是一些假设的XAML,展示了我的计划:

<ScrollViewer Name="PART_Workspace" Grid.Column="1" 
        VerticalScrollBarVisibility="Auto" 
        HorizontalScrollBarVisibility="Auto">

    <Grid x:Name="PART_Grid" RenderTransformOrigin="0.5,0.5">
        <Grid.LayoutTransform>
            <TransformGroup>
                <!-- This controls the zoom -->
                <ScaleTransform x:Name="PART_ScaleTransform"/>
            </TransformGroup>
        </Grid.LayoutTransform>

        <Canvas x:Name="PART_SelectionLayer">

            <!-- THIS REGION TO BE GENERATED AT RUNTIME -->
            <Path Style="{StaticResource SelectionBorder}"
                  StrokeThickness="! Possibly multiply this by inverse of zoom? !">
                <Path.Data>
                    <PathGeometry> <!-- one border around a region --> </PathGeometry>
                    <!-- additional borders -->
                </Path.Data>
            </Path>
            <!-- THIS REGION TO BE GENERATED RUNTIME -->

        </Canvas>

        <Viewbox Grid.Column="0" Grid.Row="0">
        <!-- This displays the bitmap, which is updated elsewhere by code -->
        <Image x:Name="PART_ImageCanvas" RenderOptions.BitmapScalingMode="NearestNeighbor"/>
        </Viewbox>
    </Grid>
</ScrollViewer>

1 个答案:

答案 0 :(得分:3)

如果您正在处理表示选择的位掩码,并且想要获得表示选区轮廓的单像素边框,则可以使用方形形态运算符来执行此操作。一旦你这样做,你就会掩盖一个模式,并覆盖它以得到行进蚂蚁的近似值。

从二进制选择掩码开始,其中选择1并取消选择0:

original selection mask

使用3px方形内核扩大遮罩并从扩张图像中减去原始图像:

Image as dilated Image showing only an outline

用棋盘图案掩盖轮廓以获得行军蚂蚁:

2x2 checkerboard mask for marching ants

覆盖原始图像上的蒙版以获得整体效果。移动棋盘以获得“追逐”效果:

chase around selection

这可以在一个相当简单的紧密循环中完成,唯一复杂的部分是扩张,您可以从AForge.net或OpenCV获得。每个像素,循环结束:

if (dialated & !selected) 
{
    if (checkerboard)
    {
        pixel = red;
    }
}

如果您已经有轮廓路径,并且希望它与已缩放的图像匹配,我会将轮廓缩放为屏幕单位。这样,BorderThicknessUseLayoutRounding都可以按预期工作。