我是一个机械工程专业的学生,正在做一个项目,自动检测车间中存在的焊接缝(接缝是要焊接的边)。这提供了焊接相关的基本术语(http://i.imgur.com/Hfwjq0w.jpg)。
为了将焊接件与其他对象分开,我拍摄了背景图像,并减去具有焊接件的前景图像,以仅获得焊接件(http://i.imgur.com/v7yBWs1.jpg)。图像相减后,背景仍然存在阴影、眩光和残馀噪声。
由于我只想自动识别没有焊接件外部边界的焊缝,所以尝试用canny算法检测焊接件图像中的边缘,并尝试使用bwareopen.I函数消除孤立的噪声,以某种方式获得了焊接件和焊缝的近似边界。我使用的阈值纯粹是试错法,因为我不知道如何自动设置阈值来检测它们。
我现在面临的问题是,我不能指定一个明确的阈值,因为这个算法应该能够识别任何材料的接缝,而不管它的表面纹理,眩光和阴影存在。我需要一些帮助,以消除眩光,阴影和孤立的点从背景减去图像。
另外,我需要帮助摆脱外部边界,只获得平滑的焊缝从起点到终点。
我尝试使用以下代码:
a=imread('imageofworkpiece.jpg'); %http://i.imgur.com/3ngu235.jpg
b=imread('background.jpg'); %http://i.imgur.com/DrF6wC2.jpg
Ip = imsubtract(b,a);
imshow(Ip) % weldment separated %http://i.imgur.com/v7yBWs1.jpg
BW = rgb2gray(Ip);
c=edge(BW,'canny',0.05); % by trial and error
figure;imshow(c) % %http://i.imgur.com/1UQ8E3D.jpg
bw = bwareaopen(c, 100); % by trial and error
figure;imshow(bw) %http://i.imgur.com/Gnjy2aS.jpg
有没有人可以建议我一种合适的方法来设置一个三叉线,并去除外部边界,只检测接缝?谢谢
发布于 2015-03-06 17:10:36
从你的图像看,焊缝通常会很暗,边缘很清晰,所以你为什么不使用它呢?
dxy=像素像素
对整个图像执行此操作(如果启用,则x必须在低于阈值的所有派生的loop!!!)
if (|dxy|
计算min
和max
强度并将阈值设置为(max-min)*scale
,其中scale
的值小于1.0
(例如,以0.02
或0.1
开头,这也适用于轴
所以计算dy[][]
...并将dx[][]
和dy[][]
结合在一起。使用OR
或by AND
logical functions
您可以使用形态过滤器或平滑阈值。在所有这一切之后,你将有像素面的焊缝
如果你需要边界框,那么只需循环所有像素,并记住最小,最大x,y
坐标…
笔记
如果你的图像会有很好的光照,那么你可以忽略导数,直接用下面的东西来设置强度阈值:
threshold = 0.5*(average_intensity+lowest_intensity)
如果你真的想要完全自动化,那么你必须使用自适应阈值。因此,在循环中尝试更多的阈值,并根据几何尺寸、位置等记住最接近所需输出的结果。
edit1终于有时间/心情来做这个了,所以
你只提供了一张图片,这远远不足以做出可靠的算法。这是的结果
如您所见,如果不进行进一步处理,这不是一种好方法
由x (10%)导出的阈值
阈值派生y (5%)
10%di/dx和1.5%di/dy的AND
组合
C++中的代码如下所示(抱歉,请不要使用Matlab):
int x,y,i,i0,i1,tr2,tr3;
pic1=pic0; // copy input image pic0 to pic1
pic2=pic0; // copy input image pic0 to pic2 (just to resize to desired size for derivation)
pic3=pic0; // copy input image pic0 to pic3 (just to resize to desired size for derivation)
pic1.rgb2i(); // RGB -> grayscale
// abs derivate by x
for (y=pic1.ys-1;y>0;y--)
for (x=pic1.xs-1;x>0;x--)
{
i0=pic1.p[y][x ].dd;
i1=pic1.p[y][x-1].dd;
i=i0-i1; if (i<0) i=-i;
pic2.p[y][x].dd=i;
}
// compute min,max derivation
i0=pic2.p[1][1].dd; i1=i0;
for (y=1;y<pic1.ys;y++)
for (x=1;x<pic1.xs;x++)
{
i=pic2.p[y][x].dd;
if (i0>i) i0=i;
if (i1<i) i1=i;
}
tr2=i0+((i1-i0)*100/1000);
// abs derivate by y
for (y=pic1.ys-1;y>0;y--)
for (x=pic1.xs-1;x>0;x--)
{
i0=pic1.p[y ][x].dd;
i1=pic1.p[y-1][x].dd;
i=i0-i1; if (i<0) i=-i;
pic3.p[y][x].dd=i;
}
// compute min,max derivation
i0=pic3.p[1][1].dd; i1=i0;
for (y=1;y<pic1.ys;y++)
for (x=1;x<pic1.xs;x++)
{
i=pic3.p[y][x].dd;
if (i0>i) i0=i;
if (i1<i) i1=i;
}
tr3=i0+((i1-i0)*15/1000);
// threshold the derivation images and combine them
for (y=1;y<pic1.ys;y++)
for (x=1;x<pic1.xs;x++)
{
// copy original (pic0) pixel for non thresholded areas the rest fill with green color
if ((pic2.p[y][x].dd>=tr2)&&(pic3.p[y][x].dd>=tr3)) i=0x00FF00;
else i=pic0.p[y][x].dd;
pic1.p[y][x].dd=i;
}
pic0
为输入图像
pic1
是输出图像
pic2,pic3
只是派生的临时存储
pic?.xy,pic?.ys
是pic?
的大小
pic.p[y][x].dd
是像素轴(dd表示访问像素为DWORD...)
正如您所看到的,周围有很多东西(在您提供的第一张图像中可以看到点头),因此您需要进一步处理它
自适应阈值:
为此,您需要知道所需的输出图像属性(不可能从单个图像输入中可靠地推断出),然后创建使用变量tr2,tr3
执行上述处理的函数。在循环中尝试tr2,tr3
的更多选项(循环所有值或迭代以获得更好的结果,并记住最佳输出(因此您还需要一些检测输出质量的函数),例如:
quality=0.0; param=0.0;
for (a=0.2;a<=0.8;a+=0.1)
{
pic1=process_image(pic0,a);
q=detect_quality(pic1);
if (q>quality) { quality=q; param=a; pico=pic1; }
}
在此之后,pic1
应该保持相对最佳的阈值图像...您应该像这样在process_image中单独处理所有阈值目标阈值必须由a
进行缩放,例如tr2=i0+((i1-i0)*a);
发布于 2015-03-07 09:18:47
这并不能解决寻找自动阈值算法的问题。但我可以帮你隔离接缝。接缝是沿y轴的(这种情况总是这样吗?)因此,我使用hough变换来分离靠近垂直线的部分。通常它会查找所有行,但我限制了theta搜索参数。我现在使用的代码恰好高亮显示了最长的线段(我直接用from the matlab website得到的),碰巧的是它是焊缝。这纯属巧合。但是使用你的bwareaopened图像作为输入,hough线检测器能够找到接缝。当然,它需要一些玩耍才能奏效,所以你会陷入寻找最优设置的原始问题上
也许这可以成为别人的跳板
a=imread('weldment.jpg'); %[http://i.imgur.com/3ngu235.jpg](https://i.imgur.com/3ngu235.jpg)
b=imread('weld_bg.jpg'); %http://i.imgur.com/DrF6wC2.jpg
Ip = imsubtract(b,a);
imshow(Ip) % weldment separated %http://i.imgur.com/v7yBWs1.jpg
BW = rgb2gray(Ip);
c=edge(BW,'canny',0.05); % by trial and error
bw = bwareaopen(c, 100); % by trial and error
figure(1);imshow(c) ;title('canny') % %http://i.imgur.com/1UQ8E3D.jpg
figure(2);imshow(bw);title('bw area open') %http://i.imgur.com/Gnjy2aS.jpg
[H,T,R] = hough(bw,'RhoResolution',1,'Theta',-15:5:15);
figure(3)
imshow(H,[],'XData',T,'YData',R,...
'InitialMagnification','fit');
xlabel('\theta'), ylabel('\rho');
axis on, axis normal, hold on;
P = houghpeaks(H,5,'threshold',ceil(0.5*max(H(:))));
x = T(P(:,2)); y = R(P(:,1));
plot(x,y,'s','color','white');
% Find lines and plot them
lines = houghlines(BW,T,R,P,'FillGap',2,'MinLength',30);
figure(4), imshow(BW), hold on
max_len = 0;
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');
% Plot beginnings and ends of lines
plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');
% Determine the endpoints of the longest line segment
len = norm(lines(k).point1 - lines(k).point2);
if ( len > max_len)
max_len = len;
xy_long = xy;
end
end
% highlight the longest line segment
plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','blue');
https://stackoverflow.com/questions/28894607
复制相似问题