在HALCON/C++中,HObject是一个基类,可以表示图像变量。另外还有三种类继承自HObject.
一个region是图像平面坐标点的集合。这样一个区域不需要被连通,而且可能还有好多洞。a region可以比实际的图像大。区域在HALCON中可以用所谓的行程编码实现。类HRegion代表HALCON/C++中的一个区域。HRegion的成员函数如下(列举几个重要的):
区域的几何变换
区域的形态学处理:
--
(void) 区域的属性:
例1
#include "HalconCpp.h"
using namespace Halcon;
void main()
{
HImage image("E:\\halcon\\images\\mreut.png"); // Reading an aerial image
HRegion region = image >= 190; // Calculating a threshold
HWindow w; // Display window
w.SetColor("red"); // Set color for regions
region.Display(w); // Display the region
HRegion filled = region.FillUp(); // Fill holes in region
filled.Display(w); // Display the region
// Opening: erosion followed by a dilation with a circle mask
HRegion open = (filled >> 4.5) << 4.5;
w.SetColor("green"); // Set color for regions
open.Display(w); // Display the region
HDPoint2D trans(-100, -150); // Vector for translation
HRegion moved = open + trans; // Translation
HRegion zoomed = moved * 2.0; // Zooming the region
}
First, an aerial image (mreut.png) is read from a file. All pixels with a gray value ≥ 190 are selected. This results in one region (region). This region is transformed by the next steps: All holes in the region are filled (FillUp), small parts of the region are eliminated by two morphological operations, first an erosion, a kind of shrinking the region, followed by a dilation, a kind of enlarging the region. The last step is the zooming of the region. For that the region is first shifted by a translation vector ( − 100, − 150) to the upper left corner and then zoomed by the factor two. Figure 6.2 shows the input image and the result of the opening operation.
HRegionArray是一个包含Region的容器。代表成员函数如下:
许多接受region的算子都接受region array作为输入参数。如形态学操作。
例2
#include "HalconCpp.h"
using namespace Halcon;
void main()
{
HImage image("E:\\halcon\\images\\control_unit.png"); // Reading an image from file
// Segmentation by regiongrowing
HRegionArray regs = image.Regiongrowing(1, 1, 4, 100);
HWindow w; // Display window
w.SetColored(12); // Set colors for regions
regs.Display(w); // Display the regions
HRegionArray rect; // New array
for (long i = 0; i < regs.Num(); i++) // For all regions in array
{ // Test size and shape of each region
if ((regs[i].Area() > 1000) && (regs[i].Compactness() < 1.5))
rect.Append(regs[i]); // If test true, append region
}
image.Display(w); // Display the image
rect.Display(w); // Display resulting regions
}
原图
变换后图像
The first step is to read an image. In this case it shows a control unit in a manufacturing environment, see figure 6.4 on the left side. By applying a regiongrowing algorithm from the HALCON library the image is segmented into regions. Each region inside the resulting region array regs is now selected according to its size and its compactness. Each region of a size larger than 1000 pixels and of a compactness value smaller than 1.5 is appended to the region array rect. After the processing of the for loop only the regions showing on the right side of figure 6.4 are left.
在Halcon中,矩阵叫做通道,一个图像可能由若干个通道组成。比如灰度图像由一个通道,而彩色图像由3个通道组成。通道的类型不仅仅是8位(btype),而且可以有其他类型(比如16 int2)以及实数类型。除了保存像素信息,每一个HALCON图像也存储所谓的domain,就是上面介绍的那种Region格式。region可以理解为感兴趣的区域,即ROI。一般除了些许异常外,halcon算子都运行在region上处理。这一点与sepera相同。
类HImage是所有继承的图像类的根类。通过使用HImage,所有不同的像素类型都可以被以统一的格式处理(多态性)。类HImage不是虚类,因此可以被实例化。如下列举了几个重要的成员函数:
几何运算
- HImage operator & (const HRegion ®) const
裁剪图像的一部分区域,然后返回此部分的图像。同reduce_domain.
点评: 此函数设计的还是很好的,比较符合直觉。一幅图像与区域做&运算,就是获取共同的部分,也就是裁剪后的图像。
例3
#include "HalconCpp.h"
using namespace Halcon;
#include "HIOStream.h"
#if !defined(USE_IOSTREAM_H)
using namespace std;
#endif
void main()
{
HImage image("E:\\halcon\\images\\mreut.png"); // Aerial image
HWindow w; // Output window
image.Display(w); // Display image
// Returning the size of the image
cout << "width = " << image.Width();
cout << "height = " << image.Height() << endl;
// Interactive drawing of a region by using the mouse
HRegion mask = w.DrawRegion();
// Reduce the domain of the image to the mask
HImage reduced = image & mask;
w.ClearWindow(); // Clear the window
reduced.Display(w); // Display the reduced image
// Applying the mean filter in the reduced image
HImage mean = reduced.MeanImage(61, 61);
mean.Display(w);
HRegion reg = reduced <= (mean -3);
reg.Display(w);
}
本例首先从文件中读取一幅灰度图像,目的是提取暗的部分。截取部分区域处理只是为了节省时间。可以通过鼠标任意画出部分区域来选择我们处理的部分图像区域。这部分区域掩模用于作为输入去截取图像(运算符&).带有61x61大小的均指掩模被应用于最后截取的图像获得均值图像。暗的像素通过应用算子<= 选取。所有的像素不超过均值-3的都选取。 具体可以参考 dyn_threshold.
HPixVal被用来访问类HImage的像素值。灰度值可以独立于他们的类型而返回和设置。
如下介绍常见的成员函数:
//构造
HPixVal(void)
Default constructor.
HPixVal(const HComplex &Val)
Constructing a pixel value from a complex number.
HPixVal(int Val)
Constructing a pixel value from an integer (int).
HPixVal(long Val)
Constructing a pixel value from a long (long).
HPixVal(HByte Val)
Constructing a pixel value from a byte (byte).
HPixVal(double Val)
Constructing a pixel value from a double (double).
HPixVal(const HPixVal &Val)
Copy constructor.
HPixVal &operator = (const HPixVal &grey)
Assignment operator.
operator HByte(void) const
Converting a pixel value to byte (0 … 255). //强制转换
operator int(void) const
Converting a pixel value to int.
operator long(void) const
Converting a pixel value to long.
operator double(void) const
Converting a pixel value to double.
operator HComplex(void) const
Converting a pixel value to Complex.
例4
#include "HalconCpp.h"
#include "HIOStream.h"
#if !defined(USE_IOSTREAM_H)
using namespace std;
#endif
using namespace Halcon;
void main()
{
HByteImage in("E:\\halcon\\images\\mreut.png"); // Aerial image
HWindow w; // Output window
in.Display(w); // Displaying the image
HByteImage out = in; // Copying the image
int width = out.Width(); // Width of the image
int height = out.Height(); // Height of the image
long end = width * height; // Number of pixel of the image
// 1. run: linear accessing
for (long k = 0; k < end; k++) {
int pix = in.GetPixVal(k); // Reading the pixel
out.SetPixVal(k, 255 - pix); // Setting the pixel
}
// Displaying the transformation
cout << "Transformed !" << endl; out.Display(w); w.Click();
cout << "Original !" << endl; in.Display(w); w.Click();
// 2. run: accessing the image via the coordinates (x,y)
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pix = in.GetPixVal(x, y); // Reading the pixel
out.SetPixVal(x, y, 255 - pix); // Setting the pixel
}
}
// Displaying the transformation
cout << "Transformed !" << endl; out.Display(w); w.Click();
cout << "Original !" << endl; in.Display(w); w.Click();
}
类HPixVal可以由上面的例子(图像取反)说明。 输入图像是一个灰度图像。首先一幅图像被复制,并且获得了图像大小。第一次运行,像素线性获得。第二次运行像素值通过(x,y)坐标获得。
点评: 本例的实质是观察int与HPixVal的隐式转换。首先SetPixVal的第三个参数应该是HPixVal,但是输入实际上是int,由于类HPixVal提供了HPixVal(int Val)
的构造函数,使得隐式转换可以成功。后面GetPixVal获取像素,又由于类HPixVal提供了operator int(void) const
的转换函数,使得int pix = in.GetPixVal(k);
是有效的。
同之前定义region的数组,HImage也定义了其数组,即HImageArray.
成员函数如下:
HImageArray(void)
Default constructor: empty array, no element.
HImageArray(const HImage ®)
Constructing an image array from a single image.
HImageArray(const HImageArray &arr)
Copy constructor.
~HImageArray(void)
Destructor.
HImageArray &operator = (const HImageArray &arr)
Assignment operator.
long Num(void) const
Returning the number of elements in the array.
HImage const &operator [] (long index) const
Reading the element i of the array. The index is in the range 0 … Num() − 1.
HImage &operator [] (long index)
Assigning an image to the element i of the array. The index index can be ≥ Num().
HImageArray operator () (long min, long max)
Selecting a subset between the lower min and upper max index.
HImageArray &Append(const HImage &image)
Appending another image to the image array.
HImageArray &Append(const HImageArray &images)
Appending another image array to the image array.
对于每一个像素类型,存在着从HImage继承的图像类,如对于像素类型byte(standard 8 bit),对应着HByteImage;对于像素类型int2(signed 16 bit),对应着HInt2Image。但是使用最广泛的是HByteImage,基本上覆盖了图像处理的大部分领域。HByteImage相对于HImage的优点是简化了像素值的访问机制。主要是因为HPixVal不再使用。除了HImage的成员函数外,HByteImage还包含了以下扩展:
像素的设置和获得
位运算
#include "HalconCpp.h"
#include "HIOStream.h"
#if !defined(USE_IOSTREAM_H)
using namespace std;
#endif
using namespace Halcon;
void main()
{
HByteImage in("E:\\halcon\\images\\mreut.png"); // Aerial image
HWindow w; // Output window
in.Display(w); // Displaying the image
HByteImage out = in; // Copying the image
int width = out.Width(); // Width of the image
int height = out.Height(); // Height of the image
long end = width * height; // Number of pixel of the image
// 1. run: linear accessing
for (long k = 0; k < end; k++) {
out[k] = 255 - in[k]; // Setting the pixel
}
// Displaying the transformation
cout << "Transformed !" << endl; out.Display(w); w.Click();
cout << "Original !" << endl; in.Display(w); w.Click();
// 2. run: accessing the image via the coordinates (x,y)
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
out(x, y) = 255 - in(x, y); // Setting the pixel
}
}
// Displaying the transformation
cout << "Transformed !" << endl; out.Display(w); w.Click();
cout << "Original !" << endl; in.Display(w); w.Click();
}
本例是例4的改造版,看起来更简洁,更像C语言的风格。访问像素不再需要get/set格式。
XLD是eXtented Line Description的简称。这种数据结构可以描述areas(即任意大小的区域或者多边形)or 任何封闭的或者打开的轮廓。与regions代表像素精度相反,XLD代表的是亚像素精度。其中有两种基本的XLD结构: 轮廓(contours)和 多边形(polygons).
与图像相似,HALCON/C++也提供了基类HXLD和一些继承自HXLD的特殊类,比如HXLDCont用于轮廓,HXLDPoly用于多边形。另外也存在一个容器类,即HXLDArray.
当以面向过程的方式调用算子时,Hobject可以被用来代表所有的图像参数,如 an image,a region,an image array.事实上,Hobject是HALCON访问内部数据的基类。并且,Hobejct也可作为HObject和HObject继承类,如HImage的基类。
Hobject有如下的成员函数:
Hobject(void)
Default constructor.
Hobject(const Hobject &obj)
Copy constructor.
virtual ~Hobject(void)
Destructor.
Hobject &operator = (const Hobject &obj)
Assignment operator.
void Reset(void)
Freeing the memory and resetting the corresponding database key.
正如前面所讲,Hobject的对象也可以包含一个图像数据的数组。但是不幸的是,Hobject没有特殊的函数区增加和选择数组成员,取而代之的是,你必须使用“The Tuple Mode”.一节所描述的算子gen_empty_obj, concat_obj, select_obj, and count_obj
代替。