分时频闪应用
一、应用场景
在工业应用中有很多产品需要需要检测多个缺陷,例如手机玻璃屏的划伤检测、凹凸点检测、脏污、崩边、等等一系列的检测。这些检测内容又不可能用一套视觉方案去解决、但是如果用多工位分别检测会有这样两个弊端:第一个在安装空间上可能不允许,第二个可能成本也会大大提高。为了方便空间的安装以及减少成本我们就可以使用分时频闪功能使用单线相机加多种角度的光源,进行分时点亮再拆图,用一次扫描检测出多种缺陷。
二、实现方法
例如需要检测4种不同的缺陷,架设四条不同的光源,搭配8K线扫相机,精度是20um,编码器机台每个信号行驶的实际距离80um.
原理:机台编码器信号AHZ同时给到光源控制器和相机。在相机端做4倍频即采集频率为4AHZ,光源控制器接四条不同角度的光源,第一个光源接收到信号之后开始点亮,第二个光源接收到信号之后延迟1/4A后开始点亮,第三个光源接收到信号之后延迟2/4A后开始点亮,第四个光源接收到信号之后延迟3/4A后开始点亮。相机端的Exposure Time <= 1/4A。每个光源的点亮时间Light Active< Exposure Time。这样最后得到一幅以四为周期的图片进行拆行得到4张在同意光源环境下拍摄的图片。
参数 光源 |
Channel0 |
Channel1 |
Channel2 |
Channel3 |
Mode |
Pluse |
|||
Output Current |
根据个通道需要设置输出电流决定光源亮度 |
|||
Pulse Delay |
0 |
Line Period |
2*Line Period |
3*Line Period |
Pulse Width |
根据各通道需要设置点亮时间,小于ExposureTime |
|||
Retrigger Delay |
0 |
这里需要调节机台的单信号行驶距离与横向精度相等。
横向精度 = FOV/Resolution, 纵向精度 = 机台速度/行频——也就是一个信号行驶的实际距离
但是的我们需要四倍频,也就是说实际一个信号走的实际距离需要是横向精度的四倍。这样才能保证四倍频之后图像不变形。
三、拆图代码
CV实现:
using namespace std;
using namespace cv;
int main()
{
string imagepath = "D:\\Users\\Administrator\\Desktop\\10.bmp";
Mat imgf = imread(imagepath, IMREAD_GRAYSCALE);//读取图像
int nl = imgf.rows;//获取图像的行数
int nc = imgf.cols;//获取图像的列数
Mat img(nl / 2, nc , CV_8UC1, Scalar(255));
Mat img1(nl / 2, nc , CV_8UC1, Scalar(255));
Mat img2(nl / 4, nc , CV_8UC1, Scalar(255));
Mat img3(nl / 4, nc , CV_8UC1, Scalar(255));
cout << "-------------------- 打印图像参数 ----------------------"<<endl;
//标志位
cout << "flags:" << imgf.flags << endl;
//图像尺寸
cout << "size:" << imgf.size << endl;
//列宽
cout << "clos:" << imgf.cols<<endl;
//行高
cout << "rows:" << imgf.rows << endl;
//维度
cout << "dims:" << imgf.dims << endl;
int i = 1, j = 0, k = 0,n = 0,m = 0,n1 = 0,m1 = 0;
int k0 =0, k1 =0, k2 =0, k3 =0;
//遍历图像的每个像素
for (int j = 0, k = 0; j < nl; j += 2, k++)
{
uchar *data = imgf.ptr<uchar>(j);
uchar *data1 = img.ptr<uchar>(k);
for (i = 0; i < nc; ++i)
{
*data1++ = *data++;
}
}
for (int j = 1, k = 0; j <nl; j += 2, k++)
{
uchar *data = imgf.ptr<uchar>(j );
uchar *data2 = img1.ptr<uchar>(k);
for (i = 0; i < nc; ++i)
{
*data2++ = *data++;
}
}
//for (int j = 2, k = 0; j < nl; j += 4, k++)
//{
// uchar *data = imgf.ptr<uchar>(j);
// uchar *data3 = img2.ptr<uchar>(k);
// for (i = 0; i < nc; ++i)
// {
// *data3++ = *data++;
// }
//}
//for (int j = 3, k = 0; j < nl; j += 4, k++)
//{
// uchar *data = imgf.ptr<uchar>(j);
// uchar *data4 = img3.ptr<uchar>(k);
// for (i = 0; i < nc; ++i)
// {
// *data4++ = *data++;
// }
//}
imwrite("D:\\Users\\Administrator\\Desktop\\img.bmp ", img);
imwrite("D:\\Users\\Administrator\\Desktop\\img1.bmp ", img1);
/*imwrite("D:\\Users\\Administrator\\Desktop\\img2.bmp ", img2);
imwrite("D:\\Users\\Administrator\\Desktop\\img3.bmp ", img3);*/
namedWindow("image");
imshow("image", imgf);
waitKey(0);
return 0;
}
waitKey(0);
return 0;
}