Halcon一日一练:创建三通道图像

本文介绍了三通道图像的基本概念,解释了彩色图像如何通过红绿蓝三个通道合成,并提供了使用Halcon进行图像生成和合成的具体示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先理解一个什么是三通道图像:

       三通道图像就是彩色图像,我们之前黑白相机或黑白电视机都是彩用的灰阶图像,即单通道图像,一般是2的8次方个灰阶,即256个灰阶。彩色图像采用RGB,红绿蓝三个通道来合成彩色图像。所以称之为三通道图像。或称为8位通道色。

       我们可以把RGB三原色想像成油盐酱醋一样,任何美味都是通过这些调味品做出来的。任何颜色也是RGB三原色按一定的比例显示出来的。三个通道就像三个控制器,去调整三个颜色的比重。

Halcon有生成图像和合成图像的算子,例程如下。

gen_image_const(Image,'byte',512,512)//生成一个图像,用byte格式
gen_image_proto(Image,ImageCleared1,255)//生成第一通道图像
gen_image_proto(Image,ImageCleared2,0)//生成第二通道图像
gen_image_proto(Image,ImageCleared3,0)//生成第三通道图像
compose3(ImageCleared1,ImageCleared2,ImageCleared3,MultiImage)//合成三个通道图像。

 

我们分别创建三个通道的图像,其中R通道的灰阶为255,合成后,我们发现一张红色的图片。如果分别去更改三个通道的灰阶,我们可以看到不同颜色的图片。

需要注意的是,三个通道的图像可以来源于不同大小的图像,新合成后的图像大小与合成前可能会不一致。

 

转载于:https://www.cnblogs.com/amosyang/p/8409438.html

``` dev_update_off() * 参数定义 GaussSize := 3 ScratchLengthMin := 100 StainAreaMin := 100 BlurThreshold := 25 // 模糊检测方差阈值 MissingDeviationLimit := 15 // 图案缺失灰度标准差阈值 PatternROISize := 0.3 // 中心检测区域占比 * 获取图像文件列表 ImageFolder := 'E:/毕业论文/瓶盖图/' list_files(ImageFolder, ['files','follow_links'], ImageFiles) tuple_regexp_select(ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles) * 创建日志文件 open_file('defect_log.txt', 'output', FileHandle) * 主循环 for ImgIndex := 0 to |ImageFiles| - 1 by 1 * 窗口管理 dev_close_window() dev_open_window(0, 0, 600, 400, 'black', WindowHandle) * 文件读取(带异常捕获) try read_image(Image, ImageFiles[ImgIndex]) catch (Exception) write_string(FileHandle, 'Failed:'+ImageFiles[ImgIndex]+'\n') continue endtry get_image_size (Image, Width, Height) GaussSize := min([int(Width/500),int(Height/300),11])*2+1 // 动态核尺寸 set_display_font (WindowHandle, 16, 'mono', 'true', 'false') dev_set_draw ('margin') dev_set_line_width (2) * 1. 图像预处理(保留V通道信息) try decompose3 (Image, R, G, B) trans_from_rgb (R, G, B, H, S, V, 'hsv') gauss_filter (V, VFiltered, GaussSize) catch (Exception) disp_message (WindowHandle, '预处理错误', 'window', 12, 12, 'red', 'true') write_string(FileHandle, 'Preprocess Error:'+ImageFiles[ImgIndex]+'\n') continue endtry * 2. 瓶盖区域定位 binary_threshold (VFiltered, Regions, 'max_separability', 'light', UsedThreshold) connection (Regions, ConnectedRegions) select_shape(ConnectedRegions, SelectedRegions, ['area','circularity'], 'and', [5000,0.7], [9999999,1.0]) fill_up (SelectedRegions, RegionFillUp) shape_trans (RegionFillUp, CapRegion, 'convex') * 3. 缺陷检测流程 * 3.1 划痕检测 reduce_domain (VFiltered, CapRegion, VReduced) equ_histo_image (VReduced, VEquHist) edges_sub_pix (VEquHist, Edges, 'canny', 1.0, 15, 25) select_shape_xld(Edges, Scratches, ['contlength','width'], 'and', [100,1], [9999,3]) gen_region_contour_xld (Scratches, ScratchesRegion, 'filled') * 3.2 污渍检测 texture_laws(VReduced, TextureEL, 'el', 5, 5) texture_laws(VReduced, TextureLE, 'le', 5, 5) add_image(TextureEL, TextureLE, TextureCombined, 0.5, 0) var_threshold(TextureCombined, Stains, 15, 15, 0.15, 1.2, 'dark') connection(Stains, ConnectedStains) select_shape(ConnectedStains, SelectedStains, 'area', 'and', StainAreaMin, 99999) * 4. 合并缺陷区域 union2(ScratchesRegion, SelectedStains, AllDefects) * 5. 后处理 connection (AllDefects, ConnectedDefects) closing_circle(ConnectedDefects, FinalDefects, 1.5) * 6. 结果显示 count_obj (FinalDefects, NumDefects) dev_display (Image) dev_set_color ('green') dev_display (CapRegion) if (NumDefects > 0) dev_set_color ('blue') dev_display (ScratchesRegion) dev_set_color ('magenta') dev_display (SelectedStains) * 添加图例说明 disp_message (WindowHandle, '检测结果:', 'window', 12, 12, 'white', 'true') disp_message (WindowHandle, '蓝色:划痕缺陷', 'window', 40, 12, 'blue', 'true') disp_message (WindowHandle, '紫色:污渍缺陷', 'window', 60, 12, 'magenta', 'true') else disp_message (WindowHandle, '检测通过:无缺陷', 'window', 12, 12, 'green', 'true') endif endfor * 关闭日志文件 close_file(FileHandle)```未处理的程序异常:HALCON算子错误,当在函数 'main' 中调用 'write_string'时.line: 45. Invalid handle type (HALCON错误代码: 2404)
最新发布
03-19
<think>嗯,用户提供的HALCON代码在运行时报错了,错误代码2404,提示“Invalid handle type”在调用write_string时。我需要帮用户解决这个问题。首先,我应该仔细看代码,找到错误发生的位置和相关部分。 根据错误信息,错误出现在第45行的write_string函数调用。用户提到是在函数'main'中,所以应该是在主循环里的某个地方。让我看一下代码的结构。 用户代码的主循环部分,在处理异常的时候有一个try-catch块。在读取图像的时候,如果出现异常,会执行write_string(FileHandle, 'Failed:'+ImageFiles[ImgIndex]+'\n'),然后continue。这里的FileHandle是在之前通过open_file创建的日志文件句柄。错误代码2404通常表示文件句柄无效,可能原因是文件没有被正确打开,或者句柄被错误地关闭了。 首先检查open_file的部分。代码中创建日志文件的语句是open_file('defect_log.txt', 'output', FileHandle)。HALCON的open_file函数参数是否正确?根据HALCON文档,open_file的第一个参数是文件名,第二个是打开模式,第三个是输出参数,即文件句柄。'output'模式应该是正确的,用于写入文件,覆盖已有内容。这里应该没问题。 但是,可能的问题是,当主循环中的某次迭代中,在打开文件后,是否有可能在某个地方意外关闭了文件句柄?例如,在循环内部是否有close_file的调用?用户代码中,主循环结束后才调用close_file(FileHandle),所以正常情况下循环内部不会关闭句柄。 另一个可能性是,当程序在第一次打开文件时失败,导致FileHandle无效。例如,路径不可写,权限问题,或者文件名无效。用户指定的日志文件名是'defect_log.txt',相对路径的话会在当前工作目录创建。如果当前目录不可写,open_file可能会失败,返回无效的句柄。但HALCON的open_file函数在失败时是否会抛出异常呢?用户代码中没有捕获open_file可能出现的异常,所以如果open_file失败,FileHandle可能是一个无效的句柄,导致后续的write_string调用出错。 因此,可能的问题在于open_file没有成功打开日志文件,导致FileHandle无效,然后在异常处理中调用write_string时使用了一个无效的句柄,从而引发错误2404。 那用户应该如何解决这个问题呢?首先,需要确保open_file成功打开了日志文件。可以在调用open_file后添加检查,或者在try-catch块中包含open_file的调用,以捕获可能的异常。 用户当前的代码中,在创建日志文件时并没有做错误处理。如果open_file失败,FileHandle可能是一个无效的句柄,这样在后续的write_string调用就会出错。因此,需要处理这种情况,例如在open_file后检查是否成功,或者使用try-catch包围open_file。 例如,修改创建日志文件的部分: try open_file('defect_log.txt', 'output', FileHandle) catch (Exception) * 处理无法创建日志文件的情况,可能输出到其他位置或提示错误 endtry 但HALCON的open_file是否会在出错时抛出异常呢?可能需要查阅HALCON的文档。根据HALCON的错误处理机制,部分函数在出错时会抛出异常,而有些则返回错误码。例如,在HDevelop中,如果设置了异常处理(通过设置dev_set_check('~give_error')),则可能不会抛出异常,而是返回错误码。但在用户代码中,使用的是try-catch块,这说明可能启用了异常处理。 如果open_file在失败时不会抛出异常,而是返回一个无效的句柄,那么即使调用open_file失败,代码也不会进入catch块,而是继续执行,导致后续使用无效句柄。在这种情况下,用户需要在调用open_file后检查句柄是否有效。 例如,HALCON可能提供某个函数来检查句柄的有效性,或者可以通过其他方式判断。例如,在HALCON中,文件句柄的有效性可能通过判断其类型或值,但具体方法可能需要查阅文档。 另一种方法是,在open_file之后,立即尝试写入一个测试行,如果失败则处理错误。例如: open_file('defect_log.txt', 'output', FileHandle) try write_string(FileHandle, 'Log started\n') catch (Exception) * 处理文件打开失败的情况 dev_display(...) 或者其他提示方式 endtry 这样,如果open_file失败,后续的write_string会抛出异常,被catch捕获,从而处理文件无法写入的问题。 回到用户代码,问题可能出现在第一次调用write_string的时候,也就是当读取图像失败时,尝试写入日志,但由于FileHandle无效,导致错误。因此,解决方法是确保open_file成功,并且FileHandle是有效的。 可能的解决步骤: 1. 检查open_file是否成功,添加异常处理或检查句柄的有效性。 2. 确保日志文件路径可写,用户是否有权限在当前目录创建文件? 3. 如果日志文件无法创建,可能需要提供绝对路径,或者调整到有权限的目录。 用户代码中的日志文件名为'defect_log.txt',使用的是相对路径,可能当前工作目录不可写。例如,如果程序运行在某个受限制的目录,如系统目录,可能会导致无法创建文件。用户可以尝试使用绝对路径,例如将日志文件路径改为明确的可写目录,如'C:/temp/defect_log.txt',或者检查当前工作目录是否有写入权限。 此外,检查open_file的返回值是否正确。在HALCON中,如果文件成功打开,FileHandle应该是一个有效的句柄。否则,可能返回错误代码。但具体处理方式可能因HALCON版本而异。 另一个可能性是,在代码的其他地方错误地关闭了FileHandle。例如,在循环内部是否有close_file的调用?查看用户代码,主循环结束后才调用close_file(FileHandle),所以循环内部没有关闭操作,应该没问题。 总结可能的解决方案: - 确保open_file成功打开日志文件,添加错误处理。 - 使用绝对路径指定日志文件。 - 检查当前目录是否有写入权限。 - 在open_file后立即测试写入日志,确保句柄有效。 例如,修改创建日志文件的部分: try open_file('defect_log.txt', 'output', FileHandle) * 测试写入 write_string(FileHandle, '开始检测,日志创建成功\n') catch (Exception) * 如果打开或写入失败,设置FileHandle为无效,并在后续处理中避免使用 FileHandle := -1 disp_message (WindowHandle, '无法创建日志文件', 'window', 12, 12, 'red', 'true') endtry 然后在需要写入日志的地方,先检查FileHandle是否有效: if (FileHandle != -1) write_string(FileHandle, ...) endif 这样,当无法创建日志文件时,后续的写入操作会被跳过,避免出现无效句柄的错误。 在用户代码中,主循环内的异常处理部分(读取图像失败时)的write_string调用,如果FileHandle无效,就会导致错误。因此,必须确保只有在FileHandle有效的情况下才执行写入操作。 因此,用户需要修改代码,在打开日志文件时进行错误处理,并在写入日志前检查句柄的有效性。 可能的代码修改如下: * 创建日志文件(带异常捕获) try open_file('defect_log.txt', 'output', FileHandle) * 可选:写入初始日志条目以确认成功 write_string(FileHandle, '日志文件已创建\n') catch (Exception) * 如果无法创建日志文件,设置FileHandle为无效值(如-1) FileHandle := -1 * 可以显示错误信息,但如果没有窗口可能无法显示 * 这里可能需要其他方式处理,比如输出到控制台 endtry * 主循环 for ImgIndex := 0 to |ImageFiles| - 1 by 1 ... try read_image(Image, ImageFiles[ImgIndex]) catch (Exception) * 在写入日志前检查FileHandle是否有效 if (FileHandle != -1) write_string(FileHandle, 'Failed:'+ImageFiles[ImgIndex]+'\n') endif continue endtry ... endfor 这样修改后,如果日志文件无法打开,FileHandle会被设置为-1,后续的写入操作会被跳过,避免出现无效句柄的错误。 另外,用户可能在HALCON环境中运行时,当前工作目录与预期不同,导致日志文件创建失败。因此,建议使用绝对路径来指定日志文件的位置,例如: open_file('C:/Users/用户名/Desktop/defect_log.txt', 'output', FileHandle) 这样可以确保文件路径有效且有写入权限。 总结,错误的原因是日志文件句柄无效,导致在写入日志时出错。解决方法包括确保日志文件正确打开,添加错误处理,检查句柄有效性,使用绝对路径,以及处理权限问题。</think>该程序存在 **文件句柄无效** 导致的HALCON错误。以下是具体分析与解决方案: --- ### **错误原因定位** 错误发生在 `write_string(FileHandle, 'Failed:'+...)` 时,核心问题是 `FileHandle` 无效。可能原因包括: 1. **日志文件未成功创建**:路径不可写、权限不足或文件名冲突 2. **句柄提前被关闭**:循环内意外关闭了文件句柄(但代码中仅在循环结束后关闭) 3. **异常未正确捕获**:`open_file` 自身错误未被处理 --- ### **逐步解决方案** #### **步骤1:增强日志文件创建时的异常处理** 修改日志创建代码段,添加异常捕获并验证句柄有效性: ```python * 创建日志文件(带异常捕获) try * 使用绝对路径确保可访问性 open_file('C:/YourPath/defect_log.txt', 'output', FileHandle) * 验证句柄有效性 write_string(FileHandle, '=== 检测日志开始 ===\n') catch (Exception) * 显示错误并终止程序 dev_close_window() throw('无法创建日志文件!请检查路径和权限。') endtry ``` #### **步骤2:主循环中增加句柄有效性检查** 在每次写入日志前检查句柄状态: ```python try read_image(Image, ImageFiles[ImgIndex]) catch (Exception) * 仅在句柄有效时写入 if (FileHandle != -1) write_string(FileHandle, 'Failed:'+ImageFiles[ImgIndex]+'\n') endif continue endtry ``` #### **步骤3:确保路径可写** - 将 `ImageFolder` 和日志路径改为 **绝对路径** - 检查文件夹是否存在且程序有写入权限 --- ### **补充优化建议** 1. **动态日志路径**: 使用系统时间生成一日志名,避免覆盖: ```python get_system_time(DateTime) LogName := 'defect_log_'+DateTime+'.txt' open_file(LogName, 'output', FileHandle) ``` 2. **资源释放**: 在程序开头添加 `dev_close_window()` 和 `close_file(FileHandle)` 确保异常退出时释放资源。 3. **错误信息细化**: 在日志中记录具体错误类型(通过 `Exception` 对象): ```python catch (Exception) ErrorMsg := Exception# '错误类型: ' + Exception# '详细信息: ' write_string(FileHandle, 'ERROR:'+ErrorMsg+'\n') endtry ``` --- ### **修改后关键代码段** ```python * 创建日志文件(绝对路径+异常验证) try ImageFolder := 'C:/YourAbsolutePath/瓶盖图/' // 确保路径存在 LogPath := 'C:/YourLogPath/defect_log.txt' open_file(LogPath, 'output', FileHandle) write_string(FileHandle, '=== 开始检测 ===\n') // 验证写入 catch (Exception) dev_close_window() throw('致命错误:无法初始化日志文件!代码终止。') endtry * 主循环中安全写入 try read_image(Image, ImageFiles[ImgIndex]) catch (Exception) if (FileHandle != -1) write_string(FileHandle, '文件读取失败: '+ImageFiles[ImgIndex]+'\n') endif continue endtry ``` --- ### **验证方法** 1. 手动创建 `C:/YourLogPath/` 目录 2. 运行修改后的程序,检查是否生成 `defect_log.txt` 3. 观察日志内容是否包含预期错误信息 通过以上修改,可解决 `Invalid handle type` 错误并提升程序鲁棒性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值