마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

opencv 투명한 이미지 덮어 쓰기 속도 향상 방법

0 추천
public static void cvAlphaCopy(Mat src1, Mat src2, Rect rect,Mat dst)
 {  
  if(src1.width()!=dst.width()||src1.height()!=dst.height())
   return;
  if(src1.width()<rect.x+src2.width()||src1.height()<rect.y+src2.height())
   return;
  double[] src2_channel=new double[4]; 
  double[] src1_channel=new double[4]; 
  double[] dst_channel=new double[4]; 
  int dx=rect.x;
  int dy=rect.y;
  int width=src2.width();
  int height=src2.height();
  for (int x = 0; x < width; ++x)
  {
   for (int y = 0; y < height; ++y)
   {  
    src2_channel=src2.get(y, x);
    src1_channel=src1.get(y+dy, x+dx);
    dst_channel[0]=(src2_channel[0]*src2_channel[3] + src1_channel[0]*(255-src2_channel[3]))/255;
    dst_channel[1]=(src2_channel[1]*src2_channel[3] + src1_channel[1]*(255-src2_channel[3]))/255;
    dst_channel[2]=(src2_channel[2]*src2_channel[3] + src1_channel[2]*(255-src2_channel[3]))/255;
    dst_channel[3]=src2_channel[3] + src1_channel[3];  
    dst.put(y+dy, x+dx, dst_channel);
   }
  }  
 }


소스 코드는 안드로이드에서 짰습니다. 



코드는 보시면 아시겠지만 src1 이미지의 Rect로 지정된 영역에 src2이미지를 덮어 씌우는 작업을 합니다. 



이때 각이미지가 투명 불투명한 부분이 있어 이를 감안하여 알파 블렌딩을 합니다. 



코드는 잘 돌아 가는데 문제는 안드로이드에서 속도가 어마어마하게 느리네요.. 512*512 하는데 거의 2~3 초정도??



PC에서 비슷하게 짠 이 함수를 돌리면 거의 속도를 느낄수 없는데도 불구하고 java라 그런지 속도 차이가 많이 납니다.&nbsp;&nbsp; 

&nbsp;

100배 아니면 적어도 10배 정도는 스피드 업해야하는데 방법이 마땅찮네요. 

&nbsp;

속도를 올릴수 있는 방법이 없을까요??

 

행쇼 (280 포인트) 님이 2014년 2월 8일 질문
행쇼님이 2014년 2월 8일 수정

1개의 답변

+1 추천
 
1. 로직의 최적화
 a. 255-src2_channel[3] 는 한번만 계산해도 되는데 한 루프에서 3번을 계산하는 듯 합니다.한번만 계산하게 바꿔보세요.
 b.  사용하는 공식이 어떻게 되는지 모르겠지만 255 로 나누게 되어 있는듯 한데.. 256 로 하면 안되나요?
256로 해도 된다면  /256 대신 >>  8 로 변경해보세요. 나누기보다 이론상 시프트 연산이 빠릅니다.
 
2. 사용언어 변경
연산속도의 경우 java -> C -> Neon 순입니다.
 
RGBA8888 -> YUV420P로 변환로직을 NEON으로 만들어 봤는데, C 코드보다 약 10배 정도 향상이 되었습니다.
NEON코드를 공부하셔야 하는 이슈가 있긴 하지만 
  java로 로직으로 만드신것을 Neon에서  변경해주시면
 원하시는대로 10배이상의  속도 향상이 될 것으로 보입니다.
 
 Neon 관련 코드는 http://hilbert-space.de/?p=22 를 참조하세요.
 
3. 연산을 미리 해둔 table 작성 
제 생각이 맞다면, src2_channel[0] ~  src2_channel[3] 의 범위가 각각 0~255 일겁니다.
그렇다면 256*256 행렬로 곱한 결과를 가진 행렬을 미리 만들어 두세요,
 
src2_channel[0]*src2_channel[3];  대신에
 maxtix[src2_channel[0], src2_channel[3]]; 를 하면, 미리 계산해둔 값이 나오는 방식이죠..
뒤에 더하기까지 하려면  256*256*256행렬을 미리 만들어, 가져오는 방식으로 하셔도 되구요.
그러면 연상량이 상당이 줄테니 속도가 빨라 질겁니다.
 
 
사악미소 (65,330 포인트) 님이 2014년 2월 8일 답변
사악미소님이 2014년 2월 8일 수정
답변감사합니다 neon 이라.. 시간이 부족하긴 하지만 공부해 봐야겠네요.. 링크도 많은 도움이 될것 같아요..
...