文章目录
OCR
光学字符识别(OCR)是阅读的技术术语,即识别符号。在HALCON中,OCR 被定义为为图像区域分配解释的任务。这些区域通常代表单个字符,因此我们认为这是读取单个符号。
在离线阶段 ,通过为每个字符呈现几个样本来训练字符。在在线阶段,图像被分割以提取代表字符的区域,然后应用 OCR 阅读器来获取每个字符的解释。
下图显示了主要步骤。第一部分是离线的,包括收集训练样本,然后应用训练。在线部分包括提取字符然后读取它们。
OCR 的优势在于训练的灵活性,它允许选择针对应用程序优化的功能。此外,您可以在基于最新技术并提供最佳性能的不同分类器之间进行选择。
作为进一步的优势,HALCON 为您提供了一组预训练字体,这些字体基于来自各个应用领域的大量训练数据。这些字体使您可以阅读文档、药品或工业产品、点印,甚至手写数字中的文本。此外,HALCON 包括用于 OCR-A 和 OCR-B 的预训练字体。
1、基本概念
OCR 分为两个主要部分:训练和阅读。 这些主要部分中的每一个都需要额外的准备步骤:
1.1 Acquire Image(s)
必须获取训练数据的生成和 OCR 本身的图像。
1.2 Segment Image(s)
无论是训练样本还是在线阅读过程,都必须从图像中提取字符。 这一步称为分段。 这意味着像 do_ocr_single_class_svm 这样的 OCR 运算符不会搜索给定感兴趣区域内的字符,而是期望分割区域,然后将其分类。
如果用于训练的样本取自真实应用图像,则训练和阅读都将采用相同的分割方法。 如果训练图像更“人工”,则可以使用更简单的方法来分割训练图像。
1.3 Train OCR
训练包括两个重要步骤:首先,为每个字符选择多个样本并将其存储在所谓的训练文件中。 在第二步中,这些文件是新创建的 OCR 分类器的输入。
如前所述,HALCON 提供了预训练的字体,即即用型分类器,它已经解决了许多 OCR 应用程序。 这些字体可以在您安装 HALCON 的文件夹的子目录 ocr 中找到。
1.4 Read Symbol
对于读取,您只需从磁盘读取经过训练的分类器,从图像中分割字符,并将分割的字符用作稍后将讨论的读取运算符之一的输入。
1.5 Destroy Classifier
当您不再需要分类器时,您可以销毁它以释放已使用的内存。
2、A First Example
这个基本概念的一个例子是下面的程序,它使用 HALCON 提供的一种预训练字体来读取图中描绘的图像中的数字。
* This example program demonstrates how to read text with the
* Automatic Text Reader using a pretrained OCR font
*
dev_update_off ()
*
* Acquire the image
read_image (Image, 'numbers_scale')
get_image_pointer1 (Image, Pointer, Type, Width, Height)
dev_close_window ()
dev_open_window (0, 0, Width, Height, 'black', WindowID)
dev_set_part (0, 0, Height - 1, Width - 1)
dev_set_line_width (2)
dev_set_color ('yellow')
dev_set_draw ('margin')
dev_display (Image)
set_display_font (WindowID, 12, 'mono', 'true', 'false')
stop ()
*
* Create the Automatic Text Reader with a pretrained OCR font
create_text_model_reader ('auto', 'Document_0-9_NoRej', TextModel)
*
* Segment the image and read the text
find_text (Image, TextModel, TextResultID)
*
* Display the segmentation results
get_text_object (Characters, TextResultID, 'all_lines')
dev_display (Image)
dev_display (Characters)
stop ()
* Display the reading results
get_text_result (TextResultID, 'class', Classes)
count_obj (Characters, Number)
for Index := 1 to Number by 1
dev_set_color ('yellow')
select_obj (Characters, SingleChar, Index)
dev_set_color ('white')
Class := Classes[Index - 1]
smallest_rectangle1 (SingleChar, Row1, Column1, Row2, Column2)
set_tposition (WindowID, Row1 - 17, (Column2 + Column1) * 0.5 - 5)
write_string (WindowID, Class[0])
endfor
stop ()
*
* Free memory
clear_text_result (TextResultID)
clear_text_model (TextModel)
3、halcon联合MFC
3.1 结果
3.2 核心代码
头文件HalconMFCDlg.h
// Local iconic variables
HObject ho_Image, ho_Characters, ho_SingleChar;
// Local control variables
HTuple hv_Pointer, hv_Type, hv_Width, hv_Height;
HTuple hv_WindowID, hv_TextModel, hv_TextResultID, hv_Classes;
HTuple hv_Number, hv_Index, hv_Class, hv_Row1, hv_Column1;
HTuple hv_Row2, hv_Column2;
//显示窗口句柄
HTuple WindowHandle1,WindowHandle2;
HTuple HWindowID; //picture control控件
cpp中实现代码
1.读取图像
void CHalconMFCDlg::OnBtnReadImage()
{
// TODO: 在此添加控件通知处理程序代码
CRect Rect;
pWnd = GetDlgItem(IDC_DISPIMAGE);
HWindowID = (Hlong)pWnd->m_hWnd;
pWnd->GetWindowRect(&Rect);
SetWindowAttr("background_color", "black");
OpenWindow(0, 0, Rect.Width(), Rect.Height(), HWindowID, "visible", "", &WindowHandle1);
//Acquire the image
ReadImage(&ho_Image, "numbers_scale1.png");
GetImagePointer1(ho_Image, &hv_Pointer, &hv_Type, &hv_Width, &hv_Height);
HDevWindowStack::Push(WindowHandle1);
if (HDevWindowStack::IsOpen())
DispObj(ho_Image, WindowHandle1);
HDevWindowStack::Push(WindowHandle1);
if (HDevWindowStack::IsOpen())
SetPart(WindowHandle1, 0, 0, hv_Height - 1, hv_Width - 1);
if (HDevWindowStack::IsOpen())
SetLineWidth(WindowHandle1, 2);
if (HDevWindowStack::IsOpen())
SetColor(WindowHandle1, "yellow");
if (HDevWindowStack::IsOpen())
SetDraw(WindowHandle1, "margin");
if (HDevWindowStack::IsOpen())
DispObj(ho_Image, HDevWindowStack::GetActive());
}
- 识别图中数字
void CHalconMFCDlg::OnBtnImageProcess()
{
// TODO: 在此添加控件通知处理程序代码
CRect Rect;
pWnd = GetDlgItem(IDC_DISPIMAGE_PROCESS);
HWindowID = (Hlong)pWnd->m_hWnd;
pWnd->GetWindowRect(&Rect);
OpenWindow(0, 0, Rect.Width(), Rect.Height(), HWindowID, "visible", "", &WindowHandle2);
HDevWindowStack::Push(WindowHandle2);
if (HDevWindowStack::IsOpen())
SetPart(WindowHandle2, 0, 0, hv_Height - 1, hv_Width - 1);
if (HDevWindowStack::IsOpen())
SetLineWidth(WindowHandle2, 2);
if (HDevWindowStack::IsOpen())
SetColor(WindowHandle2, "yellow");
if (HDevWindowStack::IsOpen())
SetDraw(WindowHandle2, "margin");
if (HDevWindowStack::IsOpen())
DispObj(ho_Image, HDevWindowStack::GetActive());
set_display_font(WindowHandle2, 12, "mono", "true", "false");
//Create the Automatic Text Reader with a pretrained OCR font
CreateTextModelReader("auto", "Document_0-9_NoRej", &hv_TextModel);
//
//Segment the image and read the text
FindText(ho_Image, hv_TextModel, &hv_TextResultID);
//
//Display the segmentation results
GetTextObject(&ho_Characters, hv_TextResultID, "all_lines");
if (HDevWindowStack::IsOpen())
DispObj(ho_Image, WindowHandle2);
if (HDevWindowStack::IsOpen())
DispObj(ho_Characters, WindowHandle2);
// stop(); only in hdevelop
//Display the reading results
GetTextResult(hv_TextResultID, "class", &hv_Classes);
CountObj(ho_Characters, &hv_Number);
{
HTuple end_val32 = hv_Number;
HTuple step_val32 = 1;
for (hv_Index = 1; hv_Index.Continue(end_val32, step_val32); hv_Index += step_val32)
{
if (HDevWindowStack::IsOpen())
SetColor(WindowHandle2, "yellow");
SelectObj(ho_Characters, &ho_SingleChar, hv_Index);
if (HDevWindowStack::IsOpen())
SetColor(WindowHandle2, "white");
hv_Class = ((const HTuple&)hv_Classes)[hv_Index - 1];
SmallestRectangle1(ho_SingleChar, &hv_Row1, &hv_Column1, &hv_Row2, &hv_Column2);
SetTposition(WindowHandle2, hv_Row1 - 17, ((hv_Column2 + hv_Column1)*0.5) - 5);
WriteString(WindowHandle2, HTuple(hv_Class[0]));
}
}
}