Halcon产品圆缺陷检测VC源码
#include "HalconCpp.h"
#include <math.h>
using namespace Halcon;
Hobject pImage;
void inspect_bottle_mouth(unsigned int nSmoothX,float* information)
{
using namespace Halcon;
// Local iconic variables
Hobject Image, ImageSmooth, Rectangle, ImageReduced;
Hobject Regions, DarkRegion, RegionOpening, RegionClosing;
Hobject RegionFillUp, RegionBorder, RegionDilation, Edges;
Hobject ContoursSplit, UnionContours, LongestContour, Circle;
Hobject RegionErosion, RegionDifference, ImageReduced1;
Hobject ImagePolar, ImagePart,ImageScaleMax, ImageMean, Connection1;
Hobject SelectedRegions, RegionUnion, XYTransRegion;
// Local control variables
HTuple StoreEmptyRegion, WindowHandle1, Index;
HTuple Width, Height, Number, area1, Row1, Column1, Length;
HTuple Row, Column, Radius, StartPhi, EndPhi, PointOrder;
//用递归过滤器平滑图像
smooth_image(pImage, &ImageSmooth, "gauss", 0.3);
//获取图像的尺寸
get_image_size(ImageSmooth, &Width, &Height);
/* //创建一个平行于坐标轴的矩形
gen_rectangle1(&Rectangle, 50, 100, Height, Width-80);
//图像与区域结合,选取矩形内的区域作为ROI
reduce_domain(ImageSmooth, Rectangle, &ImageReduced);
//利用形态学原理检测螺母
//分割图像,选取灰度值在 80~255 之间的区域
//threshold (ImageReduced, Regions, 140, 255)
threshold(ImageReduced, &Regions, 80, 255); */
//分割图像,选取灰度值在 80~255 之间的区域
threshold(ImageSmooth, &Regions, 80, 255);
//从对象数组中选择区域,对象数组的编号可以通过函数count_obj询问
//count_obj (Regions, Number)
select_obj(Regions, &DarkRegion, 1);
//消除噪点
opening_circle(DarkRegion, &RegionOpening, 3.5);
//填充缺口
closing_circle(RegionOpening, &RegionClosing, 30);
//填充孔洞
fill_up(RegionClosing, &RegionFillUp);
//获取区域的中心
area_center(RegionFillUp, &area1, &Row1, &Column1);
//减少其边界区域,boundary函数将返回区域的边界轮廓
boundary(RegionFillUp, &RegionBorder, "outer");
//对区域的边界轮廓进行膨胀操作
dilation_circle(RegionBorder, &RegionDilation, 3.5);
//图像与区域结合,选取膨胀操作后的边界轮廓内的区域作为ROI
reduce_domain(pImage, RegionDilation, &ImageReduced);
//通过边缘检测得出基圆并获知圆心,形成检测基圆。
//使用Deriche,兰瑟,沉,或Canny算子滤波器提取图像边缘
edges_sub_pix(ImageReduced, &Edges, "canny", 0.5, 20, 40);
//将轮廓分割成直线、圆和椭圆
segment_contours_xld(Edges, &ContoursSplit, "lines_circles", 5, 4, 2);
//合并属于同一个圆的区域
union_cocircular_contours_xld(ContoursSplit, &UnionContours, 0.9, 0.5, 0.5, 200,
50, 50, "true", 1);
//获取等高线或多边形的长度
length_xld(UnionContours, &Length);
//从对象数组中选择区域,对象数组的编号可以通过函数count_obj询问
select_obj(UnionContours, &LongestContour, HTuple((Length.SortIndex())[(Length.Num())-1])+1);
//拟合出检测基圆,该函数返回每一个外形的中心,半径。['ahuber'有利于减小极端值的影响]
fit_circle_contour_xld(LongestContour, "ahuber", -1, 0, 0, 3, 2, &Row, &Column,
&Radius, &StartPhi, &EndPhi, &PointOrder);
// stop(); only in hdevelop
//定义检测区域(可根据实际情况调整大小),将环形检测区域转换成矩形检测区域,便于后续处理
//根据检测基圆的中心和半径画圆
//gen_circle (Circle, Row, Column, Radius+20)
gen_circle(&Circle, Row1, Column1, 350);
//基于圆结构元素的膨胀操作
dilation_circle(Circle, &RegionDilation, 3);
//基于圆结构元素的腐蚀操作
erosion_circle(Circle, &RegionErosion, 148);
//比较膨胀操作和腐蚀操作后的两幅图像
difference(RegionDilation, RegionErosion, &RegionDifference);
//图像与区域结合,选取闭操作之后的区域作为ROI
reduce_domain(pImage, RegionDifference, &ImageReduced1);
//极坐标变换图像,极坐标变换通常被用来矫正图像中的圆形物体或被包含在圆环中的物体
//polar_trans_image (ImageReduced1, ImagePolar, Row, Column, 6.28*(Radius+50), Radius+100)
// polar_trans_image(ImageReduced1, &ImagePolar, Row1, Column1, 6.28*(330+50), 330+100);
polar_trans_image(ImageReduced1, &ImagePolar, Row1, Column1, 6.28*(360+50), 360+100);
//找到缺陷
// 选取即将作极坐标逆变换的区域
crop_part(ImagePolar, &ImagePart, 360-148, 0, 6.28*(360+50), 148);
//最大灰度值扩散的数值范围在0到255。
// scale_image_max(ImagePolar, &ImageScaleMax);
scale_image_max(ImagePart, &ImageScaleMax);
//平滑平均
mean_image(ImageScaleMax, &ImageMean, nSmoothX, 7);
//阀值分割
// dyn_threshold(ImageScaleMax, ImageMean, &Regions, 22, "dark");
dyn_threshold(ImageScaleMax, ImageMean, &Regions, 23, "dark");
//去除噪点
opening_circle(Regions, &RegionOpening, 2);
//connection:把多个region连接记起来
connection(RegionOpening, &Connection1);
//根据特性选择区域
select_shape(Connection1, &SelectedRegions, "area", "and", 360, 99999);
//联合区域
union1(SelectedRegions, &RegionUnion);
//将矩形检测区域转换成环形,使之与被检测物同时显示[极坐标逆变换]
//polar_trans_region_inv (RegionUnion, XYTransRegion, Row, Column, 6.28319, 1.367, 0, Radius-80, 6.28*Radius, 100, 1280, 1024, 'nearest_neighbor')
//polar_trans_region_inv (RegionUnion, XYTransRegion, Row1, Column1, 6.28319, 1.367, 0, 100, 5.65*Radius, 100, 1280, 1024, 'nearest_neighbor')
/* polar_trans_region_inv(RegionUnion, &XYTransRegion, Row1, Column1, 6.28319, 1.367,
0, 100, 5.65*330, 100, 1280, 1024, "nearest_neighbor"); */
/*polar_trans_region_inv(RegionUnion, &XYTransRegion, Row1, Column1, 6.28319, 0,
340-148, 360, 7.15*360, 125, 1280, 1024, "nearest_neighbor");*/
polar_trans_region_inv(RegionUnion, &XYTransRegion, Row1, Column1, 6.28319, 0,
340-148, 340, 7.15*360, 125, 1280, 1024, "nearest_neighbor");
//显示结果
count_obj(RegionUnion, &Number);
Hobject Image3;
gen_image_const(&Image3, "byte",Width, Height);
if(Number >0)
{
paint_region(XYTransRegion, Image3, &pImage, 255, "fill"); // 若图片有缺陷,则以“白色”显示缺陷
}
else
{
copy_image(Image3,&pImage); // 若图片没有缺陷,则用自己创建的黑色背景覆盖图像区域
}
}
//extern "C" _declspec(dllexport) unsigned int HCExportImage(unsigned char *pImageData,unsigned int nWidth,unsigned int nHeight,unsigned int nSmoothX,unsigned int nThresholdOffset, unsigned int nMinDefectSize)
extern "C" _declspec(dllexport) unsigned int HCExportImage(unsigned char *pImageData,unsigned int nWidth,unsigned int nHeight,unsigned int nSmoothX,float *coordinate)
{
using namespace Halcon;
HTuple Rows,Colomns;
Hobject ImageResult;
long Width1, Height1;
char type[128];
unsigned char* Pointer;
unsigned char *pImageDataForProcess = NULL;
pImageDataForProcess=new unsigned char[nWidth*nHeight];
CopyMemory(pImageDataForProcess,pImageData,nWidth*nHeight);
gen_image1(&pImage,"byte",nWidth,nHeight,(long)pImageDataForProcess);
inspect_bottle_mouth(nSmoothX,coordinate);
get_image_pointer1(pImage, (long*)&Pointer, type, &Width1, &Height1);
CopyMemory(pImageData, Pointer, Width1*Height1);
delete[] pImageDataForProcess;
return 1;
}