OpenCV Java/C++ FourierFastTransferShift(fftshift) 푸리에 변환 후 위치 재설정 함수 (Matlab - fftshift) - (1)
Matlab 에서 푸리에 변환 관련 코드를 -> OpenCV를 사용한 Java 코드로 옮기며 fftshift 함수를 찾고 있었는데, 제대로 된 코드를 못찾아서 직접 만든 코드를 올림. 퍼포먼스는 확인 안해봐서 다른 library와 비교해서 어떤지 모르겠음
OpenCV core 이용하여 shift 시키는 함수 추가 포스팅함 (아래) - 성능 향상됨
2018/11/16 - [Programming/Image Processing] - OpenCV Java/C++ FourierFastTransferShift(fftshift) 푸리에 변환 후 위치 재설정 함수 (Matlab - fftshift) - (2)
Matlab 에서 fft2(x) 함수는 OpenCV 에서 Core.dft
ifft2(x) 함수는 OpenCV 에서 Core.idft 함수로 간단하게 푸리에 변환이 가능하다.
다만, Matlab 에서는 허수까지 표현이 가능하여 하나의 디멘션(채널, 차원) 에서 실수+허수 로 값이 나타나지만.. C++/Java OpenCV에서는 일단 dft 함수를 이용하여 푸리에 변환을 하고나면 Matrix 자체의 채널이 늘어난다.
직접해본 내용은 gray 상태(1차원)에서 변환을 했기 때문에 2차원이 되었는데, 아마 항상 2배가 되지 않을까 싶다. (실수 + 허수)
채널이 실수부와 허수부로 나눠지기 때문에,
Main 함수를 보면 알수 있듯이..
1. plane1, plane2 를 따로 만들어서
2. 각각 fftShift 함수를 돌려주고 난 후(각각 어느 채널인지 channelNum이 파라미터로 필요함)
3. plane1(실수부) 와 plane2(허수부) 를 Core.merge 를 이용하여 하나의 mat으로 합쳐준다.
메모
값 자체는 Matlab 함수와 동일하게 나오는 것을 확인했지만,
허수부가 제대로 들어가있는지는 이 후에 과정을 진행해봐야 알 듯. 업데이트 예정.
for문 한개로도 될듯. stackoverflow 등에서는 circShift 로 불림.
Main 의 예제 Matrix 는 magic(4) 와 magic(3). 영어 번역
아래 Main 예제는 사분면 조정만 확인하는 예제.
푸리에변환과 함께 쓰는 예제는 따로 업데이트
//Process
//1. Input matrix for shift
//2. Iterate from begin to the end
// 2.1. Separate each quadrant
//3. Iterate from begin to the end
// 3.1. Align each quadrant shifted
//4. Return matrix shifted
//처리과정
//1. 매트릭스 입력 받는다.
//2. 전체 반복한다.
// 2.1. 각 사분면 값을 분리 저장해둔다.
//3. 전체 반복한다.
// 3.1. 각 사분면 변환 위치값에 배치한다.
//4. 바뀐 매트릭스 반환한다.
/**
* FFT Shift core
* firstQuadrant to thirdQuadrant, secondQuadrant to fourthQuadrant
* thirdQuadrant to firstQuadrant, fourthQuadrant to secondQuadrant
*
* @param in
* @param out
*/
private void fftShift(Mat in, Mat out, int channelNum) {
int midRows = (in.rows() + 1) / 2;
int midCols = (in.cols() + 1) / 2;
double[] firstQuadrant = new double[(in.rows() - midRows) * midCols];
double[] secondQuadrant = new double[midRows * midCols];
double[] thirdQuadrant = new double[midRows * (in.cols() - midCols)];
double[] fourthQuadrant = new double[(in.rows() - midRows) * (in.cols() - midCols)];
int firstQuadrantIndex = 0;
int secondQuadrantIndex = 0;
int thirdQuadrantIndex = 0;
int fourthQuadrantIndex = 0;
for (int i = 0; i < in.rows(); ++i)
{
for (int j = 0; j < in.cols(); ++j)
{
if (i < midRows && j < midCols) // 2 quad
{
secondQuadrant[secondQuadrantIndex++] = in.get(i, j)[channelNum];
}
else if (i < midRows) // 1 quad
{
firstQuadrant[firstQuadrantIndex++] = in.get(i, j)[channelNum];
}
else if (j < midCols) // 3 quad
{
thirdQuadrant[thirdQuadrantIndex++] = in.get(i, j)[channelNum];
}
else // 4 quad
{
fourthQuadrant[fourthQuadrantIndex++] = in.get(i, j)[channelNum];
}
}
}
firstQuadrantIndex = 0;
secondQuadrantIndex = 0;
thirdQuadrantIndex = 0;
fourthQuadrantIndex = 0;
if (in.rows() % 2 != 0) // even length or not
{
midRows -= 1;
midCols -= 1;
}
for (int i = 0; i < in.rows(); ++i)
{
for (int j = 0; j < in.cols(); ++j)
{
if (i < midRows && j < midCols) // 2 quad
{
out.put(i, j, fourthQuadrant[fourthQuadrantIndex++]);
}
else if (i < midRows) // 1 quad
{
out.put(i, j, thirdQuadrant[thirdQuadrantIndex++]);
}
else if (j < midCols) // 3 quad
{
out.put(i, j, firstQuadrant[firstQuadrantIndex++]);
}
else // 4 quad
{
out.put(i, j, secondQuadrant[secondQuadrantIndex++]);
}
}
}
}
==========================================================
Main 함수 example
public static void main(String args[]) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
FourierFastTransfer fft = new FourierFastTransfer();
int sizeSet = 4;
// int sizeSet = 3;
//Test magic number(4), (3)
Mat inputMat = Mat.zeros(sizeSet, sizeSet, CvType.CV_32F);
inputMat.put(0, 0, 16);
inputMat.put(0, 1, 2);
inputMat.put(0, 2, 3);
inputMat.put(0, 3, 13);
inputMat.put(1, 0, 5);
inputMat.put(1, 1, 11);
inputMat.put(1, 2, 10);
inputMat.put(1, 3, 8);
inputMat.put(2, 0, 9);
inputMat.put(2, 1, 7);
inputMat.put(2, 2, 6);
inputMat.put(2, 3, 12);
inputMat.put(3, 0, 4);
inputMat.put(3, 1, 14);
inputMat.put(3, 2, 15);
inputMat.put(3, 3, 1);
// inputMat.put(0, 0, 8);
// inputMat.put(0, 1, 1);
// inputMat.put(0, 2, 6);
// inputMat.put(1, 0, 3);
// inputMat.put(1, 1, 5);
// inputMat.put(1, 2, 7);
// inputMat.put(2, 0, 4);
// inputMat.put(2, 1, 9);
// inputMat.put(2, 2, 2);
Mat outputMat = Mat.zeros(sizeSet, sizeSet, CvType.CV_32F);
Core.dft(inputMat, outputMat, Core.DFT_COMPLEX_OUTPUT, 0);
for (int i = 0; i < outputMat.rows(); ++i)
{
for (int j = 0; j < outputMat.cols(); ++j)
{
System.out.print(outputMat.get(i, j)[1] + " ");
}
System.out.println("");
}
System.out.println("");
Mat plane1 = Mat.zeros(outputMat.rows(), outputMat.cols(), CvType.CV_32F);
Mat plane2 = Mat.zeros(outputMat.rows(), outputMat.cols(), CvType.CV_32F);
fft.fftShift(outputMat, plane1, 0);
fft.fftShift(outputMat, plane2, 1);
List<Mat> listMat = Arrays.asList(plane1, plane2);
Core.merge(listMat, outputMat);
for (int i = 0; i < outputMat.rows(); ++i)
{
for (int j = 0; j < outputMat.cols(); ++j)
{
System.out.print(outputMat.get(i, j)[0] + " ");
}
System.out.println("");
}
System.out.println("");
fft.ifftShift(outputMat, plane1, 0);
fft.ifftShift(outputMat, plane2, 1);
listMat = Arrays.asList(plane1, plane2);
Core.merge(listMat, outputMat);
for (int i = 0; i < outputMat.rows(); ++i)
{
for (int j = 0; j < outputMat.cols(); ++j)
{
System.out.print(outputMat.get(i, j)[1] + " ");
}
System.out.println("");
}
System.out.println("");
}
======================================================
Something else you might like...?
2019/01/25 - [Life/Health care] - L-Arginine 아르기닌 usage/side effects/dosage 효능/부작용/성인,소아 용법(3)
2019/01/25 - [Life/Health care] - Maca 마카 usage/side effects/dosage 효능/부작용/성인,소아 용법(2)
'Programming' 카테고리의 다른 글
OpenCV (Java) How to change Mat to Image, and save (OpenCV Mat 에서 Image 변환, 저장) (0) | 2018.10.16 |
---|---|
Java enum class 자바 이넘 클래스 (Singleton design pattern 처럼 사용방법) (0) | 2018.10.16 |
Java parse double dataType after dot, 자바 소수점 이하 출력개수 조절 (0) | 2018.10.11 |
C++ Math - floor/ceil/round (내림/올림/반올림) (0) | 2018.09.27 |
Java 자바 Math class - round/ceil/floor/abs (반올림/올림/내림/절대값) (0) | 2018.09.27 |