朱莉娅中的 vcat StackOverflowError

cla*_*lax 3 julia

我编写了一个函数来检测数组中的对象。在本例中,我使用它来清除接触图像边框的白色物体。但问题是,vcat 中总是存在 StackOverFlowError 并且它发生在不同的行(取决于图像)。这是一个最小的工作示例。它适用于第二张图像,但不适用于第一张图像: 测试.png 测试2.png

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);
Run Code Online (Sandbox Code Playgroud)

您只需更改我的代码中图像的名称即可。如果您需要更多信息,请告诉我。多谢。

干杯,放松

col*_*ang 5

与许多函数式编程语言不同,Julia 不会优化尾递归(当函数因调用而结束时重用堆栈帧)。因此,在您的情况下,您的递归函数很可能会达到最大堆栈深度,具体取决于操作系统的线程堆栈大小。

不幸的是,Julia 核心团队决定不优先考虑尾部调用优化,因为他们认为此类功能不是必须的。事实上,人们经常可以将代码重构为循环。

老实说,尾部调用优化非常困难,许多其他具有函数式编程范式的编程语言也缺乏它。