2011-09-05 2 views
4

내 소프트웨어의 한 부분으로, 프로젝터가 화면에 수직이 아닌 각도로 표시 될 때 얻을 수있는 삭제 표시/키스톤 효과를 피하기 위해 키스톤 교정 필터를 작성하려고합니다.소프트웨어 키스톤 보정 알고리즘

현재 나는 뭔가 작동하고 있지만 매우 느립니다 (전체 이미지의 경우 ~ 100ms). 이상적으로는 (10ms 범위에서 가급적 빨리) 무언가를 원하는 것이 이상적입니다. 픽셀 다음이 새로운 배열에 새 이미지의 RGB 내용을 설정 한 새 배열로 내가 원하는 픽셀을 복사하여 전체 이미지 픽셀 :

public BufferedImage getCorrectedImage() { 
    double width = originalImage.getWidth(null) * 0.5; 
    double increment = (originalImage.getWidth(null) - width)/originalImage.getHeight(); 

    BufferedImage ret = new BufferedImage(originalImage.getWidth(null), originalImage.getHeight(null), BufferedImage.TYPE_INT_ARGB); 

    for (int h = 0; h < originalImage.getHeight(); h++) { 
     int[] arr = new int[originalImage.getWidth()]; 
     for (int w = 0; w < originalImage.getWidth(); w++) { 
      arr[w] = originalImage.getRGB(w, h); 
     } 
     int[] newPixels = getShortLine(arr, (int) (width + 0.5)); 

     for (int w = 0; w < originalImage.getWidth(); w++) { 
      ret.setRGB(w, h, newPixels[w]); 
     } 
     width += increment; 
    } 

    return ret; 
} 

private int[] getShortLine(int[] original, int newSize) { 
    int[] newArr = new int[original.length]; 
    double scale = original.length/newSize; 
    int start = (original.length - newSize)/2; 
    int end = original.length - ((original.length - newSize)/2); 
    for (int i = start; i < end-1; i++) { 
     newArr[i] = original[(int) ((i - start) * scale)]; 
    } 
    return newArr; 
} 

무엇이 일에 대해 최선의 방법이 될 것이다? 사용자 정의 affine 변환은 처음에 내가 보려는 것이었지만 올바른 방향으로 나를 가리키는 코드/예제를 찾을 수 없었습니다. 위의 결과보다 더 나은 결과를 얻을 수있는 방법이 있습니까?

+4

OpenCV를 살펴보십시오. 그것은 정말로 빠르며 사실상 모든 렌즈 왜곡을 교정하는 기능을 가지고 있습니다. 유망한 Java 래퍼가 있습니다. http://code.google.com/p/javacv/ – Blender

+0

@Blender 덕분에 그 부분을 살펴 보겠습니다. 가능한 한 유일한 것은 자바로 무언가를 원합니다. 따라서 크로스 플랫폼을 유지할 수 있습니다 - 물론 JNA 매직이 있지만 가능하면 피하고 싶습니다. 이 경우 – berry120

+0

을 입력하십시오. 그렇다면 어떻게 도움을 줄지는 모르겠지만 OpenCV 또는 다른 라이브러리의 소스 코드를 보면 그렇게 빨리 수행 할 수 있습니다. – Blender

답변

1

기존 코드의 속도를 높이려면 몇 가지 방법이 있습니다. 주의를 요하는 메모는 코드를 더 복잡하고 어렵게 만들고 ... 디버그 할 것입니다. 그러나 알고리즘이 작동하고 있다면, 더 나은 성능을 위해 리팩토링 너무 어려운되지 않을 수 있습니다

  • 시도가 덜 -보다 분명있을 경우 알고리즘에서 병목 현상을 볼 수있는 profiler를 사용하여.
  • getCorrectedImage 함수의 루프를 통해 매번 새로운 배열을 재 할당합니다. 그것은 시간이 지남에 따라 합쳐질 메모리 할당입니다. 작업 속도를 높이려면 하나의 배열 (픽셀 너비/높이가 가장 큰)을 만들고 함수의 수명 내내 다시 사용하십시오. 실제로 사용되는 내용을 추적하려면 몇 가지 추가 변수를 추가해야 할 수도 있습니다.
  • getShortLine 메소드를 인라이닝 해 봅니다. JVM이 런타임에 인라인 할 것인지 또는 그것이 실행되는지 여부를 확인하는 방법이 있는지 확실하지 않습니다. 어쨌든 배열 재사용이 성능을 발휘하지 못한다면 인라인을 "수동으로"수행 할 가치가있을 것입니다.
  • 이 기능을 정적으로 설정할 수도 있습니다. originalImage 멤버를 변수로 전달하기 만하면됩니다. 이는 특히 클래스 로딩에 대해 성능에 약간의 영향을 미칠 수 있습니다. 유일한 변수가 이미지 인 것처럼 보이고 쉽게 전달 될 수 있기 때문에 정적으로 정의하는 것도 의미가 있습니다. 다른 클래스 멤버 종속성이 없습니다. 유틸리티 클래스에서 유틸리티 메소드가되어야하는 것처럼 보입니다.

전체적으로 Java로 작성된 ImageJ을 확인하십시오.

+0

제안 해 주셔서 감사합니다. 실제로 위의 두 가지를 모두 시도했지만 이미 읽기 쉽도록 위 코드에서 제외했습니다. 둘 다 이미지의 RGB 내용을 개별 픽셀이 아닌 배열로 한 줄씩 가져 오는 것과 같이 주변에서 연주 한 다른 것들과 마찬가지로 측정 가능한 작은 증가를 제공했습니다. 그들은 속도를 약간 향상 시키지만, 내가 찾고있는 것은 아닙니다. 가능한 한 비디오 프레임과 같은 실시간 처리 작업을 원합니다. – berry120

+0

병목 현상을 찾기 위해 프로파일 러를 사용해 보셨습니까? (내 대답에 옵션으로 추가했습니다.) –

+0

불행히도 명백한 병목 현상이 없었으며 처리 시간이 알고리즘 전체에 균등하게 분산되었습니다. 절대적으로 단일 문장/루프는 처리 시간의 90 %를 취하지 않습니다. – berry120

관련 문제