我编写了一个检测数组中对象的函数。在这种情况下,我用它来清除触摸图像边框的白色物体。但问题是,vcat中始终存在StackOverFlowError,它出现在不同的行(取决于图像)。这是一个最低限度的工作示例。它适用于第二个图像,但不适用于第一个图像:
using Images
function getImChars(I::Array)
charAr=copy(I);
indexMax=find(x->(x==1),charAr);
(h,w)=size(charAr);
# check border values
(r,c)=ind2sub(size(charAr),indexMax);
indexBorderR1=find(x->(x==1),r);
indexBorderR2=find(x->(x==h),r);
indexBorderR=[indexBorderR1;indexBorderR2];
indexBorderC1=find(x->(x==1),c);
indexBorderC2=find(x->(x==w),c);
indexBorderC=[indexBorderC1;indexBorderC2];
borderPixels=[999;999]; # initialize def value FIX
for bRc=1:length(indexBorderR)
borderPixels=[borderPixels [r[indexBorderR[bRc]];c[indexBorderR[bRc]]]];
end
for bCc=1:length(indexBorderC)
borderPixels=[borderPixels [r[indexBorderC[bCc]];c[indexBorderC[bCc]]]];
end
borderPixels=borderPixels[:,2:end];
(rbP,cbP)=size(borderPixels);
fcharAr=[];
for k=1:cbP
bP=[borderPixels[:,k];false;false;false;false];
locObj1=[];
locObj2=[];
locObj3=[];
locObj4=[];
locObj5=[];
locObj6=[];
if(charAr[bP[1],bP[2]]==0)
continue;
else
charAr[bP[1],bP[2]]=0;
end
recGetCharClearBorders(true,false,h,w,bP,locObj1,locObj2,locObj3,locObj4,locObj5,locObj6,charAr);
end
return charAr;
end
function recGetCharClearBorders(firstFlag::Bool,doNotAdd::Bool,h::Int,w::Int,hP::Array,locObj1::Array,locObj2::Array,locObj3::Array,locObj4::Array,locObj5::Array,locObj6::Array,imAr::Array)
leftPoint=[hP[1];hP[2]-1;0;0;0;0];
rightPoint=[hP[1];hP[2]+1;0;0;0;0];
topPoint=[hP[1]-1;hP[2];0;0;0;0];
bottomPoint=[hP[1]+1;hP[2];0;0;0;0];
# check if it is not out of bounds and relative directions
if(topPoint[1]!=0)
if(imAr[topPoint[1],topPoint[2]]==1)
hP[4]=1;
end
end
if(bottomPoint[1]!=(h+1))
if(imAr[bottomPoint[1],bottomPoint[2]]==1)
hP[6]=1;
end
end
if(leftPoint[2]!=0)
if(imAr[leftPoint[1],leftPoint[2]]==1)
hP[3]=1;
end
end
if(rightPoint[2]!=(w+1))
if(imAr[rightPoint[1],rightPoint[2]]==1)
hP[5]=1;
end
end
# add first elements
if(firstFlag)
locObj1=collect(hP[1]);
locObj2=collect(hP[2]);
locObj3=collect(hP[3]);
locObj4=collect(hP[4]);
locObj5=collect(hP[5]);
locObj6=collect(hP[6]);
firstFlag=false;
else
# if first element of locObj was deleted actual point should not get pushed to array
if(!doNotAdd)
push!(locObj1,hP[1]);
push!(locObj2,hP[2]);
push!(locObj3,hP[3]);
push!(locObj4,hP[4]);
push!(locObj5,hP[5]);
push!(locObj6,hP[6]);
imAr[hP[1],hP[2]]=0;
end
end
goL=false;
goT=false;
goR=false;
goB=false;
doNotAdd=false;
if(length(locObj1)!=0)
# always take and check first elements of locObj
hPfInLoc=[locObj1[1],locObj2[1],locObj3[1],locObj4[1],locObj5[1],locObj6[1]];
hPl=[hPfInLoc[1];hPfInLoc[2]-1;0;0;0;0];
hPt=[hPfInLoc[1]-1;hPfInLoc[2];0;0;0;0];
hPr=[hPfInLoc[1];hPfInLoc[2]+1;0;0;0;0];
hPb=[hPfInLoc[1]+1;hPfInLoc[2];0;0;0;0];
compL=false;
compT=false;
compR=false;
compB=false;
# check bounds and if array values have changed
if(hPt[1]!=0)
if(imAr[hPt[1],hPt[2]]!=0)
compT=true;
end
end
if(hPb[1]!=(h+1))
if(imAr[hPb[1],hPb[2]]!=0)
compB=true;
end
end
if(hPl[2]!=0)
if(imAr[hPl[1],hPl[2]]!=0)
compL=true;
end
end
if(hPr[2]!=(w+1))
if(imAr[hPr[1],hPr[2]]!=0)
compR=true;
end
end
# define directions and set defined direction false in locObj
if((locObj3[1]==1)& compL)
locObj3[1]=0;
goL=true;
elseif((locObj4[1]==1)& compT)
locObj4[1]=0;
goT=true;
elseif((locObj5[1]==1)& compR)
locObj5[1]=0;
goR=true;
elseif((locObj6[1]==1)& compB)
locObj6[1]=0;
goB=true;
else
if (length(locObj1)==1)
locObj=[];
else # if everything is zero delete first rows of arrays
deleteat!(locObj1,1);
deleteat!(locObj2,1);
deleteat!(locObj3,1);
deleteat!(locObj4,1);
deleteat!(locObj5,1);
deleteat!(locObj6,1);
doNotAdd=true;
return recGetCharClearBorders(firstFlag,doNotAdd,h,w,hP,locObj1,locObj2,locObj3,locObj4,locObj5,locObj6,imAr);
end
end
end
#execute choosen direction
if(goL)
return recGetCharClearBorders(firstFlag,doNotAdd,h,w,hPl,locObj1,locObj2,locObj3,locObj4,locObj5,locObj6,imAr);
end
if(goT)
return recGetCharClearBorders(firstFlag,doNotAdd,h,w,hPt,locObj1,locObj2,locObj3,locObj4,locObj5,locObj6,imAr);
end
if(goR)
return recGetCharClearBorders(firstFlag,doNotAdd,h,w,hPr,locObj1,locObj2,locObj3,locObj4,locObj5,locObj6,imAr);
end
if(goB)
return recGetCharClearBorders(firstFlag,doNotAdd,h,w,hPb,locObj1,locObj2,locObj3,locObj4,locObj5,locObj6,imAr);
end
end
# execute test procedure
Im=Images.load("Test.png");
Im=data(Im);
imAr=map(Float64,Im);
resIm=getImChars(imAr);
save("Imout.png",resIm);
您只需要在我的代码中更改图像的名称。如果您需要更多信息,请告诉我。非常感谢。
干杯,clax
答案 0 :(得分:4)
与许多函数式编程语言不同,Julia不优化尾递归(当函数以调用结束时重用堆栈帧)。因此,在您的情况下,您的递归函数很可能会达到最大堆栈深度,具体取决于您的操作系统的线程堆栈大小。
不幸的是,Julia核心团队决定不优先考虑Tail呼叫优化,因为他们认为这种功能不是必须的。实际上,人们通常可以将代码重构为循环。
Afaik,尾部调用优化非常困难,许多其他具有函数式编程范式的编程语言也缺乏它。
答案 1 :(得分:2)
Took a few minutes needed to run and fixup the tail recursion. Is the following replacement for recGetCharClearBorders
performing correctly:
function recGetCharClearBorders(firstFlag::Bool,doNotAdd::Bool,h::Int,w::Int,hP::Array,locObj1::Array,locObj2::Array,locObj3::Array,locObj4::Array,locObj5::Array,locObj6::Array,imAr::Array,recdepth,recloc)
while true
leftPoint=[hP[1];hP[2]-1;0;0;0;0];
rightPoint=[hP[1];hP[2]+1;0;0;0;0];
topPoint=[hP[1]-1;hP[2];0;0;0;0];
bottomPoint=[hP[1]+1;hP[2];0;0;0;0];
# check if it is not out of bounds and relative directions
if(topPoint[1]!=0)
if(imAr[topPoint[1],topPoint[2]]==1)
hP[4]=1;
end
end
if(bottomPoint[1]!=(h+1))
if(imAr[bottomPoint[1],bottomPoint[2]]==1)
hP[6]=1;
end
end
if(leftPoint[2]!=0)
if(imAr[leftPoint[1],leftPoint[2]]==1)
hP[3]=1;
end
end
if(rightPoint[2]!=(w+1))
if(imAr[rightPoint[1],rightPoint[2]]==1)
hP[5]=1;
end
end
# add first elements
if(firstFlag)
locObj1=collect(hP[1]);
locObj2=collect(hP[2]);
locObj3=collect(hP[3]);
locObj4=collect(hP[4]);
locObj5=collect(hP[5]);
locObj6=collect(hP[6]);
firstFlag=false;
else
# if first element of locObj was deleted actual point should not get pushed to array
if(!doNotAdd)
push!(locObj1,hP[1]);
push!(locObj2,hP[2]);
push!(locObj3,hP[3]);
push!(locObj4,hP[4]);
push!(locObj5,hP[5]);
push!(locObj6,hP[6]);
imAr[hP[1],hP[2]]=0;
end
end
goL=false;
goT=false;
goR=false;
goB=false;
doNotAdd=false;
if(length(locObj1)!=0)
# always take and check first elements of locObj
hPfInLoc=[locObj1[1],locObj2[1],locObj3[1],locObj4[1],locObj5[1],locObj6[1]];
hPl=[hPfInLoc[1];hPfInLoc[2]-1;0;0;0;0];
hPt=[hPfInLoc[1]-1;hPfInLoc[2];0;0;0;0];
hPr=[hPfInLoc[1];hPfInLoc[2]+1;0;0;0;0];
hPb=[hPfInLoc[1]+1;hPfInLoc[2];0;0;0;0];
compL=false;
compT=false;
compR=false;
compB=false;
# check bounds and if array values have changed
if(hPt[1]!=0)
if(imAr[hPt[1],hPt[2]]!=0)
compT=true;
end
end
if(hPb[1]!=(h+1))
if(imAr[hPb[1],hPb[2]]!=0)
compB=true;
end
end
if(hPl[2]!=0)
if(imAr[hPl[1],hPl[2]]!=0)
compL=true;
end
end
if(hPr[2]!=(w+1))
if(imAr[hPr[1],hPr[2]]!=0)
compR=true;
end
end
# define directions and set defined direction false in locObj
if((locObj3[1]==1)& compL)
locObj3[1]=0;
goL=true;
elseif((locObj4[1]==1)& compT)
locObj4[1]=0;
goT=true;
elseif((locObj5[1]==1)& compR)
locObj5[1]=0;
goR=true;
elseif((locObj6[1]==1)& compB)
locObj6[1]=0;
goB=true;
else
if (length(locObj1)==1)
locObj=[];
else # if everything is zero delete first rows of arrays
deleteat!(locObj1,1);
deleteat!(locObj2,1);
deleteat!(locObj3,1);
deleteat!(locObj4,1);
deleteat!(locObj5,1);
deleteat!(locObj6,1);
doNotAdd=true;
continue
end
end
end
#execute choosen direction
if(goL)
hP = hPl
continue
end
if(goT)
hP = hPt
continue
end
if(goR)
hP = hPr
continue
end
if(goB)
hP = hPb
continue
end
break
end
end
Somehow the output image turned on its side in my run.