Opencv&Halcon混合编程
前言
Halcon 具备一些非常强大的算子,特别是其中的模板匹配功能,因此在建立自己的解决方案时,灵活的运用Halcon与OpenCV往往会事半功倍。
1. 编写halcon代码
以halcon中的find_scaled_shape_model为例。
2. 导出halcon代码到C++
删除掉被宏定义注释的代码,主要关注action函数里面的代码。
删除窗口显示相关代码。
3. 头文件和库文件
添加头文件和库文件路径
将DLL文件拷贝到可执行文件目录下
4. 格式转换
Halcon C++ 中存在两种数据结构Hobject和HTuple。
Halcon中没有很多复杂的数据结构,在Opencv中使用结构体或类表示的数据结构在Halcon中通常采用一系列变量来表示。
HObject不都是image类型,只有image类型才可以转为Mat。
Halcon中的数据结构:
Image
可以转化为Mat。
Region
可以使用Halcon的region_to_bin将区域转为二进制字节图像,再转为Mat。
region_to_bin (Region, BinImage, 255, 0, Width, Height)
Mat HalconCV::RegionToMat(HObject ho_Region, HTuple hv_Width, HTuple hv_Height)
{
HObject ho_BinImage;
RegionToBin(ho_Region, &ho_BinImage, 255, 0, hv_Width, hv_Height);
return HobjectToMat(ho_BinImage);
}
Contour
可以使用Halcon中的contour_point_num_xld(Contour : : : Length)将轮廓转化为一系列点集。
例如在Opencv中使用Rect来表示矩形,在halcon中则使用四个单独的变量表示,所以解析起来也很容易。
字符串与HTuple互转
char *pImageName = "D:/data/temp.png";
HTuple hv_path;
hv_path = (HTuple)(pImageName);
string path = hv_path.S();
Double与HTuple互转
HTuple hv_data;
hv_data = 10.0;
double data = hv_path.D();
Mat转HObject
HObject matToHobject(Mat& image)
{
HObject Hobj = HObject();
int hgt = image.rows;
int wid = image.cols;
int i;
// CV_8UC3
if (image.type() == CV_8UC3)
{
vector<Mat> imgchannel;
split(image, imgchannel);
Mat imgB = imgchannel[0];
Mat imgG = imgchannel[1];
Mat imgR = imgchannel[2];
uchar* dataR = new uchar[hgt*wid];
uchar* dataG = new uchar[hgt*wid];
uchar* dataB = new uchar[hgt*wid];
for (i = 0; i < hgt; i++)
{
memcpy(dataR + wid*i, imgR.data + imgR.step*i, wid);
memcpy(dataG + wid*i, imgG.data + imgG.step*i, wid);
memcpy(dataB + wid*i, imgB.data + imgB.step*i, wid);
}
GenImage3(&Hobj, "byte", wid, hgt, (Hlong)dataR, (Hlong)dataG, (Hlong)dataB);
delete[]dataR;
delete[]dataG;
delete[]dataB;
dataR = NULL;
dataG = NULL;
dataB = NULL;
}
// CV_8UCU1
else if (image.type() == CV_8UC1)
{
uchar* data = new uchar[hgt*wid];
for (i = 0; i < hgt; i++)
memcpy(data + wid*i, image.data + image.step*i, wid);
GenImage1(&Hobj, "byte", wid, hgt, (Hlong)data);
delete[] data;
data = NULL;
}
return Hobj;
}
HObject转Mat
Mat HobjectToMat(HObject Hobj)
{
HTuple htCh = HTuple();
HTuple cTyp
Mat Image;
ConvertImageType(Hobj, &Hobj, "byte");
CountChannels(Hobj, &htCh);
HTuple wid;
HTuple hgt;
int W, H;
if (htCh[0].I() == 1)
{
HTuple ptr;
GetImagePointer1(Hobj, &ptr, &cType, &wid, &hgt);
W = (Hlong)wid;
H = (Hlong)hgt;
Image.create(H, W, CV_8UC1);
uchar* pdata = (uchar*)ptr[0].I();
memcpy(Image.data, pdata, W*H);
}
else if (htCh[0].I() == 3)
{
HTuple ptrR, ptrG, ptrB;
GetImagePointer3(Hobj, &ptrR, &ptrG, &ptrB, &cType, &wid, &hgt);
W = (Hlong)wid;
H = (Hlong)hgt;
Image.create(H, W, CV_8UC3);
vector<Mat> vecM(3);
vecM[2].create(H, W, CV_8UC1);
vecM[1].create(H, W, CV_8UC1);
vecM[0].create(H, W, CV_8UC1);
uchar* pr = (uchar*)ptrR[0].I();
uchar* pg = (uchar*)ptrG[0].I();
uchar* pb = (uchar*)ptrB[0].I();
memcpy(vecM[2].data, pr, W*H);
memcpy(vecM[1].data, pg, W*H);
memcpy(vecM[0].data, pb, W*H);
merge(vecM, Image);
}
return Image;
}
5. 混合编程
混合编程最重要的就是对输入输出的格式转换,中间的处理过程可以封装为函数,不做考虑。
#include "halconcv.h"
using namespace HalconCpp;
void action()
{
// Local iconic variables
HObject ho_Image, ho_Region, ho_ConnectedRegions;
HObject ho_SelectedRegions, ho_RegionFillUp, ho_RegionDilation;
HObject ho_ImageReduced, ho_Model, ho_ModelTrans, ho_ImageSearch;
// Local control variables
HTuple hv_Width, hv_Height;
HTuple hv_ModelID, hv_Area, hv_RowRef, hv_ColumnRef, hv_HomMat2D;
HTuple hv_Row, hv_Column, hv_Angle, hv_Scale, hv_Score;
HTuple hv_Row1, hv_Column1, hv_Row2, hv_Column2;
HTuple hv_I;
cv::Mat src = cv::imread("green-dot.png", 1);
ho_Image = HalconCV::matToHobject(src);
GetImageSize(ho_Image, &hv_Width, &hv_Height);
Threshold(ho_Image, &ho_Region, 0, 128);
Connection(ho_Region, &ho_ConnectedRegions);
SelectShape(ho_ConnectedRegions, &ho_SelectedRegions, "area", "and", 10000, 20000);
FillUp(ho_SelectedRegions, &ho_RegionFillUp);
DilationCircle(ho_RegionFillUp, &ho_RegionDilation, 5.5);
ReduceDomain(ho_Image, ho_RegionDilation, &ho_ImageReduced);
CreateScaledShapeModel(ho_ImageReduced, 5, HTuple(-45).TupleRad(), HTuple(90).TupleRad(),
"auto", 0.8, 1.0, "auto", "none", "ignore_global_polarity", 40, 10, &hv_ModelID);
GetShapeModelContours(&ho_Model, hv_ModelID, 1);
AreaCenter(ho_RegionFillUp, &hv_Area, &hv_RowRef, &hv_ColumnRef);
VectorAngleToRigid(0, 0, 0, hv_RowRef, hv_ColumnRef, 0, &hv_HomMat2D);
AffineTransContourXld(ho_Model, &ho_ModelTrans, hv_HomMat2D);
cv::Mat image_search = cv::imread("green-dots.png", 1);
ho_ImageSearch = HalconCV::matToHobject(image_search);
FindScaledShapeModel(ho_ImageSearch, hv_ModelID, HTuple(-45).TupleRad(), HTuple(90).TupleRad(),
0.8, 1.0, 0.5, 0, 0.5, "least_squares", 5, 0.8, &hv_Row, &hv_Column, &hv_Angle,
&hv_Scale, &hv_Score);
{
HTuple end_val26 = (hv_Score.TupleLength())-1;
HTuple step_val26 = 1;
for (hv_I=0; hv_I.Continue(end_val26, step_val26); hv_I += step_val26)
{
double offset_x = hv_Column[hv_I];
double offset_y = hv_Row[hv_I];
double angle = hv_Angle[hv_I];
double scale = hv_Scale[hv_I];
cv::circle(image_search, cv::Point2f(offset_x, offset_y), 1, cv::Scalar(0, 255, 0), 5);
std::cout << offset_x << " "<< offset_y << " "<< angle << " "<< scale << std::endl;
}
}
cv::imshow("src", src);
waitKey(0);
ClearShapeModel(hv_ModelID);
}
int main(int argc, char *argv[])
{
int ret = 0;
try
{
SetSystem("use_window_thread", "true");
SetSystem("width", 512);
SetSystem("height", 512);
action();
}
catch (HException &exception)
{
fprintf(stderr," Error #%u in %s: %s\n", exception.ErrorCode(),
(const char *)exception.ProcName(),
(const char *)exception.ErrorMessage());
ret = 1;
}
return ret;
}
上一篇: 图像插值-双线性插值(bilinear)
下一篇: 图像插值-双三次插值(bicubic)