본문 바로가기

Programming

OpenCV Java/C++ FourierFastTransferShift(fftshift) 푸리에 변환 후 위치 재설정 함수 (Matlab - fftshift) - (1)

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...?




2018/11/16 - [Programming/Image Processing] - OpenCV Java/C++ FourierFastTransferShift(fftshift) 푸리에 변환 후 위치 재설정 함수 (Matlab - fftshift) - (2)


2018/11/28 - [Programming/Image Processing] - OpenCV How to get min/max value from matrix, 매트릭스 최소값/최대값. Java,c++,cpp,imageprocessing


2018/11/28 - [Programming/Image Processing] - OpenCV How to handle single channel image matrix each pixel, add/subtract/multiply/division (1), 이미지 매트릭스 각 픽셀단위 값 조정하기 (영상처리, image processing) (1)


2018/11/27 - [Programming/Image Processing] - OpenCV Java complexNumber mat conjugation, 자바 켤레복소수 example code 예제코드



2019/02/08 - [Algorithm/Leet Code] - LeetCode #400 NthDigit. Algorithm,알고리즘,LeetCode,Codefights,CodeSignal,코드파이트,코드시그널,예제,문제해결능력,example,c++,java,재귀,recursive,datastructure,techinterview,coding,코딩인터뷰,기술면접

2019/02/03 - [Algorithm/Leet Code] - LeetCode #393 UTF-8 Validation. Algorithm,알고리즘,LeetCode,Codefights,CodeSignal,코드파이트,코드시그널,예제,문제해결능력,example,c++,java,재귀,recursive,datastructure,techinterview,coding,코딩인터뷰,기술면접

2019/02/03 - [Algorithm/Leet Code] - LeetCode #398 RandomPickIndex. Algorithm,알고리즘,LeetCode,Codefights,CodeSignal,코드파이트,코드시그널,예제,문제해결능력,example,c++,java,재귀,recursive,datastructure,techinterview,coding,코딩인터뷰,기술면접

2019/02/01 - [Algorithm/Leet Code] - LeetCode #905 SortArrayByParity. Algorithm,알고리즘,LeetCode,Codefights,CodeSignal,코드파이트,코드시그널,예제,문제해결능력,example,c++,java,재귀,recursive,datastructure,techinterview,coding,코딩인터뷰,기술면접

2019/01/31 - [Algorithm/Leet Code] - LeetCode #593 ValidSquare. Algorithm,알고리즘,LeetCode,Codefights,CodeSignal,코드파이트,코드시그널,예제,문제해결능력,example,c++,java,재귀,recursive,datastructure,techinterview,coding,코딩인터뷰,기술면접


2019/01/12 - [Algorithm/Code Fights (Code Signal)] - Aracade Intro #60 sudoku. Algorithm,알고리즘,Codefights,CodeSignal,코드파이트,코드시그널,예제,문제해결능력,example,c++,java,재귀,recursive

2019/01/12 - [Algorithm/Code Fights (Code Signal)] - Aracade Intro #59 spiralNumbers. Algorithm,알고리즘,Codefights,CodeSignal,코드파이트,코드시그널,예제,문제해결능력,example,c++,java,재귀,recursive

2019/01/08 - [Algorithm/Code Fights (Code Signal)] - Aracade Intro #58 messageFromBinaryCode. Algorithm,알고리즘,Codefights,CodeSignal,코드파이트,코드시그널,예제,문제해결능력,example,c++,java,재귀,recursive

2019/01/07 - [Algorithm/Code Fights (Code Signal)] - Aracade Intro #57 fileNaming. Algorithm,알고리즘,Codefights,CodeSignal,코드파이트,코드시그널,예제,문제해결능력,example,c++,java,재귀,recursive



2019/01/14 - [Programming/Java] - 자바 메모리 누수 체크/확인/고치는 방법, Memory leak check/fix in Java application, cleanCode/좋은코드/oop/객체지향



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)

2019/01/17 - [Life/Health care] - Zinc 아연 usage/side effects/dosage/fatigue/supplement/antioxidant/효능/부작용/성인,소아 용법/건강/피로회복/영양제/항산화



2019/01/29 - [Programming/Programming Language] - 클린코딩/더 나은 코딩을 하는 10가지 방법, 10 Tips for clean code/ better code/ quality code.

2019/01/30 - [Programming/Software Architecture] - What is Object Oriented Design/Artchitecture? 객체지향 디자인/설계란? java,c++,softwareArchitecture,designPattern