判断一个像素点是不是在封闭轮廓内部

本文介绍了一种用于判断像素点是否位于二值图像中封闭区域内的方法。通过孔洞填充技术,将封闭区域内的所有像素标记为已填充状态,再检查指定像素点是否处于这些已填充像素之中。

 

%函数功能:判断一个像素点是否在封闭区间里面

%输入参数:i(横坐标),j(纵坐标),二值图像,1为目标区域

%输出参数:0表示不再轮廓内,1表示在轮廓内

%算法思想:因为封闭区间如果是凸多边形的话,直接可以用像素点所在的直线与多边形的交点判断,

%但是提取出的骨骼轮廓是不规则的,所以先孔洞填充,填充的部分变为目标区域集合S,如果像素点在集合

%S里面,则在区域里面,如果不属于S则在区域外面

%zsj写于2011-1-8

function result=judege_in_or_out(i,j,f);

%先对f孔洞填充

%f=imread('F:/数字图象处理/segmentation/第一节骨骼轮廓.bmp');

f_fill=imfill(f,'holes');

figure

imshow(f_fill);

[f_fill_row,f_fill_col]=find(f_fill==1);

num_1=length(f_fill_row);

result=0;

for row=1:num_1

    for col=1:num_1

        if(i==f_fill_row(row)&&j==f_fill_col(col))

            result=1;

        end

    end

end

 

 

<think>我们面临的问题:在SVG轮廓内自动生成间距为2mm、直径为0.5mm的小圆点。 思路: 1. 我们需要一个SVG路径(轮廓),假设我们已经有了这个路径(例如,用户提供的图形)。 2. 我们需要在轮廓内部生成均匀分布的小圆点,圆点直径为0.5mm,间距为2mm(这里间距可以理解为相邻圆点中心之间的距离)。 3. 由于SVG的坐标系单位可以是任意单位,但我们需要毫米(mm),因此我们需要知道SVG的视口大小和用户单位与毫米的转换关系。在SVG中,1用户单位通常等于1px,但我们可以通过设置viewBox和物理尺寸来调整。为了精确的物理尺寸,我们可以使用单位(如mm)或通过转换比例。 然而,在SVG中直接使用毫米单位是可行的,因为SVG支持绝对单位。但是,请注意,在屏幕上显示时,不同的设备分辨率可能会影响实际大小。如果我们需要精确的物理尺寸,可以在导出时设置DPI( dots per inch)或者使用打印设置的固定尺寸。 步骤: 1. 确定轮廓的边界:我们需要知道轮廓的边界框(bounding box),以便在内部生成点阵。 2. 生成点阵:在边界框内,按照2mm的间距生成网格点(横竖间隔都是2mm)。 3. 过滤点:只保留落在轮廓内部的点。 4. 绘制圆点:每个点用半径为0.25mm(直径0.5mm)的圆表示。 但是,如何判断是否轮廓内?我们可以使用SVG的<clipPath>或者使用JavaScript(如果是在浏览器中操作)进行点包容性测试。然而,用户要求的是生成SVG文件,所以我们需要一个生成静态SVG的方法。 由于我们无法在静态SVG中直接进行动态计算,因此我们需要在生成SVG之前完成这些计算。这意味着我们需要使用某种编程语言(如JavaScript、Python等)来生成SVG代码。 但是,用户并没有指定运行环境,所以我们将提供两种思路: a) 使用JavaScript在浏览器中生成(如果需要交互式网页) b) 使用服务器端语言(如Python)生成静态SVG文件 由于问题要求生成SVG,我们假设用户希望得到一段SVG代码(静态),或者一个生成该SVG的方法。 这里我们以JavaScript(在浏览器中运行)为例,因为SVG通常与前端结合。但是,请注意,如果用户希望完全在服务器端生成,也可以使用类似逻辑的Python(使用svgwrite等库)。 实现步骤(JavaScript): 1. 获取SVG路径元素:假设我们有一个SVG路径,其id为"outline"。 2. 计算路径的边界框:使用`getBBox()`方法。 3. 创建点阵:在边界框内,以2mm为步长,生成网格点。 4. 使用`document.createElementNS`创建圆点(circle元素),并设置圆心坐标和半径(0.25mm)。 5. 使用`path.isPointInFill(point)`方法(需要将点转换为SVGPoint)判断是否在路径内部。注意:这个方法在SVG2中支持,但旧浏览器可能不支持,所以也可以考虑使用第三方库(如paper.js)或者自己实现一个简单的点包容测试(对于复杂多边形可能不够准确)。 然而,由于我们要求的是静态SVG,我们可以在浏览器中生成后,将生成的SVG代码保存下来。 但是,用户可能希望直接得到一个静态的SVG文件,而不需要运行JavaScript。因此,我们可能需要一个离线工具或者使用服务器端生成。 考虑到用户可能没有编程环境,我们也可以提供一种使用现有工具的方法,但遗憾的是,目前没有现成的工具可以直接实现这个功能。所以,我们重点介绍编程方法。 下面是一个使用JavaScript的示例代码,该代码在浏览器中运行,可以生成一个包含轮廓内部圆点的SVG图像。 注意:由于我们使用毫米单位,我们需要在SVG根元素上设置适当的视口(viewport)和用户单位。我们可以设置`width`和`height`为毫米单位,并设置`viewBox`以匹配坐标系统。 假设我们的轮廓路径数据已经定义,并且整个SVG的视口设置为实际物理尺寸(例如,宽度和高度以毫米为单位)。 示例代码: 首先,我们创建一个SVG元素,设置命名空间,并设置其宽度和高度(以毫米为单位)。 然后,添加轮廓路径。 接着,生成点阵并过滤,只添加在轮廓内部的点。 但是,由于我们使用物理单位(mm),在计算边界框和点坐标时,我们需要注意一致性。 然而,在浏览器中,使用`getBBox()`返回的是用户单位(通常是px),但我们的SVG可能使用mm单位。因此,我们需要确保整个SVG的坐标系统使用毫米。我们可以设置viewBox,使得用户单位等于1mm。 例如:设置viewBox为"0 0 100 50",然后设置width="100mm" height="50mm",这样每个用户单位就是1mm。 因此,我们可以在用户单位(等同于毫米)下工作。 步骤: 1. 创建SVG元素,设置viewBox和宽高(以毫米为单位,但viewBox使用相同的数值范围)。 2. 添加轮廓路径(使用用户单位,即毫米单位)。 3. 计算轮廓的边界框(使用getBBox,返回的是用户单位下的坐标,即毫米)。 4. 在边界框内生成网格点(x和y以2mm为步长)。 5. 对于每个点,判断是否轮廓内部(使用path元素的isPointInFill方法,注意点坐标需要是SVGPoint对象)。 6. 如果在内部,则创建一个圆,圆心为该点,半径为0.25(因为直径0.5mm,所以半径0.25mm)。 下面是示例代码: ```html <!DOCTYPE html> <html> <body> <svg id="svg" width="200mm" height="200mm" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"> <!-- 定义一个轮廓,例如一个圆形 --> <path id="outline" d="M100,50 a50,50 0 1,1 0,100 a50,50 0 1,1 0,-100Z" fill="none" stroke="black"/> </svg> <script> document.addEventListener('DOMContentLoaded', function() { const svg = document.getElementById('svg'); const outline = document.getElementById('outline'); // 获取轮廓的边界框 const bbox = outline.getBBox(); // 圆点间距2mm,直径0.5mm(半径0.25mm) const spacing = 2; const radius = 0.25; // 创建SVG点用于测试 const point = svg.createSVGPoint(); // 生成网格点 for (let x = bbox.x; x <= bbox.x + bbox.width; x += spacing) { for (let y = bbox.y; y <= bbox.y + bbox.height; y += spacing) { point.x = x; point.y = y; // 判断是否轮廓内部 if (outline.isPointInFill(point)) { const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); circle.setAttribute('cx', x); circle.setAttribute('cy', y); circle.setAttribute('r', radius); circle.setAttribute('fill', 'black'); svg.appendChild(circle); } } } }); </script> </body> </html> ``` 注意:上述代码在浏览器中运行,并且使用了一个圆形作为轮廓。用户可以将轮廓路径替换为任意形状。 但是,这种方法有两个限制: 1. 依赖于浏览器对`isPointInFill`的支持(现代浏览器支持)。 2. 轮廓必须是路径(path)元素,并且是封闭的。 如果轮廓是复杂的形状,可能会有性能问题(因为每个点都要测试)。 另外,我们也可以使用<clipPath>来达到类似效果,但是生成的点阵是一个矩形网格,然后通过clipPath裁剪到轮廓内部。但是,这样生成的圆点仍然是矩形排列,只是被裁剪了,所以边缘可能不完整(我们要求的是完整的圆点,且间距固定,所以边缘处可能不足2mm)。因此,我们选择逐个判断是否内部。 关于服务器端生成:可以使用Python的svgwrite库和cairosvg(用于点包容测试)或其他几何库(如shapely)来处理。但这里不展开。 如果用户希望使用其他工具,如Inkscape,Inkscape有内置的“创建平铺克隆”功能,但是间距和大小需要手动调整,而且不能自动适应任意轮廓内部。所以编程方法更灵活。 因此,我们推荐使用编程方法生成。 相关问题: 1. 如何将生成的SVG用于打印? 2. 如何调整圆点的间距和大小? 3. 除了圆形,能否使用其他形状(如方形)填充轮廓? 4. 如果轮廓有多个不相连的部分,如何分别填充? 注意:上述代码只是一个示例,实际应用中可能需要根据具体轮廓调整。另外,对于非常大的轮廓,生成的点数可能很多,导致性能问题,可以考虑使用Web Worker或优化算法(例如使用空间分割减少测试点)。 引用: [^1]: 在SVG中,我们可以使用路径(path)来定义任意形状,然后通过编程方式在内部生成点阵。 [^2]: 使用JavaScript操作SVG是一种常见的方法,但也可以使用服务器端生成。 [^3]: 对于点包容测试,SVG2的`isPointInFill`方法提供了简单的判断。</think>在SVG轮廓内自动生成间距约2mm、直径为0.5mm的小圆点,可以通过编程实现或使用设计工具。以下是两种推荐方法: ### 方法1:使用JavaScript编程生成(推荐) ```javascript function generateDotsInSVG(svgPath, spacing=2, diameter=0.5) { // 1. 获取轮廓边界框 const bbox = svgPath.getBBox(); const radius = diameter / 2; // 2. 创建点阵容器 const patternGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g'); // 3. 生成网格点阵 for (let x = bbox.x; x < bbox.x + bbox.width; x += spacing) { for (let y = bbox.y; y < bbox.y + bbox.height; y += spacing) { // 4. 检查点是否轮廓内 if (isPointInPath(svgPath, x, y)) { const dot = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); dot.setAttribute('cx', x); dot.setAttribute('cy', y); dot.setAttribute('r', radius); patternGroup.appendChild(dot); } } } // 5. 添加到SVG svgPath.parentNode.appendChild(patternGroup); } // 点包容性检测函数(简化示例) function isPointInPath(path, x, y) { const point = path.ownerSVGElement.createSVGPoint(); point.x = x; point.y = y; return path.isPointInFill(point); } // 使用示例 const myPath = document.getElementById('myShape'); generateDotsInSVG(myPath, 2, 0.5); ``` #### 关键参数说明: - `spacing=2`:圆点中心间距(单位:mm) - `diameter=0.5`:圆点直径(单位:mm) - 使用SVG DOM API进行精确坐标计算[^1] ### 方法2:使用Inkscape工具(图形界面) 1. **创建轮廓** - 绘制或导入矢量图形 - 转换为路径(Path > Object to Path) 2. **生成点阵** ```python # 扩展脚本示例(需安装Inkscape) import inkex class DotPattern(inkex.EffectExtension): def effect(self): path = self.selected[self.options.id] bbox = path.bounding_box() for x in range(int(bbox.left), int(bbox.right), 2): for y in range(int(bbox.top), int(bbox.bottom), 2): if path.hit_test((x, y)): self.svg.circle(center=(x, y), radius=0.25) ``` 3. **参数调整** - 通过命令行传递参数: ``` inkscape --with-gui --extension-script=dot_pattern.py --id=path123 --spacing=2 --diameter=0.5 ``` ### 注意事项 1. **单位转换**:SVG默认使用像素(px),需确保文档单位设置为mm: ```svg <svg width="100mm" height="100mm" viewBox="0 0 100 100"> ``` 2. **性能优化**:对于复杂轮廓,可使用四叉树空间分割减少计算量 3. **边缘处理**:添加边缘偏移避免圆点被裁剪: ```javascript const offset = spacing/2; for (x = bbox.x + offset; ... ) ``` ### 输出效果示例 ```svg <svg width="50mm" height="50mm" viewBox="0 0 50 50"> <path id="heart" d="M25,5 C15,0,0,10,15,30 Q25,40,35,30 C50,10,35,0,25,5Z"/> <g fill="black"> <!-- 生成的圆点 --> <circle cx="12.5" cy="15" r="0.25"/> <circle cx="14.5" cy="15" r="0.25"/> ...约200个圆点... </g> </svg> ``` >[!TIP] >对于印刷场景,建议导出为PDF时保留矢量属性,避免分辨率损失[^2]。复杂轮廓可能需要使用`even-odd`填充规则检测内部点[^3]。 --- ### 相关问题 1. 如何确保SVG中的毫米单位在不同设备上显示一致? 2. 除了圆形,如何在轮廓内生成其他形状的重复图案(如三角形/六边形)? 3. 如何处理带孔洞的复杂SVG路径的内部填充? 4. 有哪些开源库可以直接实现SVG内部的图案生成? [^1]: SVG基础 | 绘制SVG文字,描边和填充操作 [^2]: 使用Photoshop生成SVG的详细方法 [^3]: Java通过SVG导出图片的技术实现
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值