2013-04-11 4 views
1

Я работаю над графическим исполнением частотной фильтрации изображения. Мой код отлично работает на CPU (я использовал что-то вроде this), но я потратил целый день, пытаясь сделать ту же работу на GPU - без успеха. Я хочу применить фильтр в частотной области, поэтому мне нужен полный (сложный) результат прямого преобразования. Я прочитал, что мне нужно передать две сложные матрицы (src и dst) для пересылки dft для получения полного спектра (32FC2). Тем не менее, я не получаю то же изображение после обратного преобразования (возвращаемое изображение очень искажено).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

Мне потребовалось еще несколько часов, но я в конечном итоге решил проблему. Есть два варианта

1) в режиме реального к сложному (CV_32FC1 -> CV_32FC2) вперед и комплекса к реальному (CV_32FC2 -> CV_32FC1) обратный
В результате прямого преобразования более узкую матрицу спектра (newWidth = oldWidth/2 + 1, как описано в documentation). Это не CSS компактная матрица, как в случае не-gpu dft. Это сложная матрица, которая использует тот факт, что спектр частот симметричен. Следовательно, любой фильтр также может быть применен здесь с ускорением от выполнения почти половинного меньшего умножения, чем во втором случае. В этом случае следующие флаги должны быть установлены:

  • вперед -> 0
  • обратное -> DFT_INVERSE | DFT_REAL_OUTPUT | DFT_SCALE

Это отлично подойдет для меня. Не забудьте объявить ранее должным образом GpuMat, используемый для их типов (CV_32FC1 или CV_32FC2)

2) комплексно к сложному (CV_32FC2 -> CV_32FC2) вперед и комплекса к сложному (CV_32FC2 -> CV_32FC2) обратная Полный спектр спектра (CV_32FC2) производится в прямом DFT. В этом случае флаги

  • вперед -> 0
  • обратное -> DFT_INVERSE

Результатом обратного преобразования является комплексной матрицей (CV_32FC2), поэтому вам нужно разделить его и экстракт желаемый результат от нулевого канала. Позже данные должны быть скорректированы явно:

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); 

Как просто! Я понятия не имею, почему я раньше этого не встречал. Я решил опубликовать его любым способом, так как у кого-то может быть такая же проблема или нужны какие-то рекомендации.

 Смежные вопросы

  • Нет связанных вопросов^_^