2013-04-11 2 views
1

이미지의 주파수 필터링을 GPU로 구현하고 있습니다. 내 코드는 CPU에서 훌륭하게 작동합니다 (저는 this과 같은 것을 사용했습니다).하지만 하루 종일 GPU에서 동일한 작업을하려고 노력했습니다. 성공하지 못했습니다. 따라서 주파수 도메인에서 필터를 적용하여 순방향 변환의 전체 (복잡한) 결과가 필요합니다. 전체 스펙트럼 (32FC2)을 얻기 위해 dft를 전달하기 위해 두 개의 복잡한 행렬 (src 및 dst)을 전달해야한다는 것을 읽었습니다. 그러나, 나는 역변환 후에 동일한 이미지를 얻지 못한다. (리턴 된 이미지는 매우 왜곡된다.) (가장 가까운 결과)OpenCV gpu :: dft 역변환 후 왜곡 된 이미지

내 코드 :

gpu.img1 = gpu::GpuMat(vrH, imgWidth, CV_32FC2); 
gpu.img2 = gpu::GpuMat(vrH, imgWidth, CV_32FC2); 
gpu.img4 = gpu::GpuMat(vrH, imgWidth, CV_32FC1); 
gpu.img5 = gpu::GpuMat(vrH, imgWidth, CV_8UC1); 

Mat planes[] = {imageIn, Mat::zeros(imageIn.size(), CV_32FC1)}; 
merge(planes, 2, imageIn); 

gpu::Stream stream; 
gpu.img1.upload(imageIn); 

gpu::dft(gpu.img1, gpu.img2, gpu.img1.size(), 0, stream); 
gpu::dft(gpu.img2, gpu.img4, gpu.img1.size(), DFT_INVERSE | DFT_REAL_OUTPUT | DFT_SCALE, stream); 
stream.enqueueConvert(gpu.img4, gpu.img5, CV_8U); 

stream.waitForCompletion(); 
gpu.img5.download(imageOut); 
namedWindow("processed",1); imshow("processed", imageOut); waitKey(1000); 

여러분의 도움과 제안이 많이 감사합니다.

답변

1

몇 시간이 더 걸렸지 만 결국 문제가 해결되었습니다. > CV_32FC2) 순방향 및 착물에 리얼 (CV_32FC2 - - 전진의 결과로서
역> CV_32FC1) 좁은 스펙트럼 변환 매트릭스 두 가지

1) 실제 투 복합 CV_32FC1들은 (거기 (newWidth = oldWidth/2 + 1은 documentation에서 설명한대로). non-gpu dft의 경우와 마찬가지로 CSS compact 매트릭스가 아닙니다. 주파수 스펙트럼이 대칭이라는 사실을 사용하는 복합 행렬입니다. 따라서 두 번째 경우보다 거의 절반 정도 적은 곱셈을 수행하여 속도를 높이면 모든 필터를 여기에 적용 할 수 있습니다. 이 경우 다음과 같은 플래그를 설정해야합니다

  • 앞으로 -> 0
  • 역 -> DFT_INVERSE | DFT_REAL_OUTPUT | DFT_SCALE

이것은 나를 위해 훌륭했습니다. 제대로 앞에서 자신의 유형 (CV_32FC1 또는 CV_32FC2)

2)에 사용되는 GpuMat를 선언하는 것을 잊지 복잡한-에 복잡한 CV_32FC2 (-> CV_32FC2) 앞으로 복잡한 - 투 - 복합 (CV_32FC2 - 역> CV_32FC2) 전체 크기 스펙트럼 (CV_32FC2)은 순방향 DFT에서 생성됩니다. 따라서이를과 추출물을 분리 할 필요가 반대의 결과 변환

복잡한 매트릭스 (CV_32FC2)이다 DFT_INVERSE> -> 0

  • 역 -이 경우, 플래그는 순방향

    • 있다 제로 채널로부터의 요구 된 결과 나중에 데이터를 명시 적으로 조정해야합니다.

      Mat lenaAfter; 
      Mat lena = imread("C:/Users/Fundespa/Desktop/lena.jpg", CV_LOAD_IMAGE_GRAYSCALE); 
      
      lena.convertTo(lena, CV_32F, 1); 
      
      std::vector<Mat> planes; 
      planes.push_back(lena); 
      planes.push_back(Mat::zeros(lena.size(), CV_32FC1)); 
      merge(planes, lena); 
      
      gpu::GpuMat lenaGPU = gpu::GpuMat(512, 512, CV_32FC2); 
      gpu::GpuMat lenaSpectrum = gpu::GpuMat(512, 512, CV_32FC2); 
      gpu::GpuMat lenaOut = gpu::GpuMat(512, 512, CV_32FC2); 
      lenaGPU.upload(lena); 
      
      gpu::dft(lenaGPU, lenaSpectrum, lenaGPU.size(), 0, stream); 
      int c = lenaSpectrum.channels(); 
      Size s = lenaSpectrum.size(); 
      gpu::dft(lenaSpectrum, lenaOut, lenaGPU.size(), DFT_INVERSE, stream); 
      
      gpu::split(lenaOut, splitter, stream); 
      stream.waitForCompletion(); 
      splitter[0].download(lenaAfter); 
      // lenaOut.download(lenaAfter); 
      
      c = lenaAfter.channels(); 
      
      double n,x; 
      minMaxIdx(lenaAfter, &n, &x); 
      
      lenaAfter.convertTo(lenaAfter, CV_8U, 255.0/x); 
      
      namedWindow("lena after",1); imshow("lena after", lenaAfter); waitKey(1000); 
      

      간단합니다. 나는 왜 내가이 일찍 오지 않았는지 전혀 모른다. 나는 거기에 누군가가 같은 문제가 있거나지도가 필요할 수도 있기 때문에 어떤 식 으로든 게시하기로 결정했습니다.