# Filtering a CCS spectrum

I need to filter (multiply) my OpenCV DFT matrix with some custom filter mask (like a band-pass filter). With DFT_COMPLEX_OUTPUT, applying this mask is quite trivial (just multiply real and imaginary channels with the filter mask), and I have that working well.

I am doing milions of these operations, and now I want to speed things up by using the CCS format. How should I change the filter mask, to get the same results? The CCS format is relatively non-trivial, so I guess the trasformation that needs to be done on the filter mask will be non-trivial aswell. I am aware of the function mulSpectrums(), but that is for multiplying two CCS matrices. I have one CCS matrix from DFT, and one real (or complex by duplicating channels) matrix, which is the filter, and which is not in the CCS format, so I cannot use mulSpectrums(). Is there an simple way to convert a matrix to a CCS format?

Seems to me like quite a common problem, but I was unable to find anything. I guess everyone that does filtering in the frequency domain just uses the significantly slower DFT_COMPLEX_OUTPUT?

So, can I have my cake, and eat it too? (without losing my hair over figuring out how to implement a normal Mat → CCS Mat function)

the matrix shape given there is a little broken but that’s the best I can find

https://docs.opencv.org/4.x/d2/de8/group__core__array.html#gadd6cf9baf2b8b704a11b5f04aaf4f39d

the bottom right half needs to go in the bottom right corner. in the bottom left block, they didn’t bother with the “obvious” 4th and 5th column.

I think it should look something like this:

\begin{bmatrix} Re Y_{0,0} & Re Y_{0,1} & Im Y_{0,1} & Re Y_{0,2} & Im Y_{0,2} & \cdots & Re Y_{0,N/2-1} & Im Y_{0,N/2-1} & Re Y_{0,N/2} \\ Re Y_{1,0} & Re Y_{1,1} & Im Y_{1,1} & Re Y_{1,2} & Im Y_{1,2} & \cdots & Re Y_{1,N/2-1} & Im Y_{1,N/2-1} & Re Y_{1,N/2} \\ Im Y_{1,0} & Re Y_{2,1} & Im Y_{2,1} & Re Y_{2,2} & Im Y_{2,2} & \cdots & Re Y_{2,N/2-1} & Im Y_{2,N/2-1} & Im Y_{1,N/2} \\ ... & ... & ... & ... & ... & ... & ... & ... & ... \\ Re Y_{M/2-1,0} & Re Y_{M-3,1} & Im Y_{M-3,1} &...&...& ... & Re Y_{M-3,N/2-1} & Im Y_{M-3,N/2-1}& Re Y_{M/2-1,N/2} \\ Im Y_{M/2-1,0} & Re Y_{M-2,1} & Im Y_{M-2,1} &...&...& ... & Re Y_{M-2,N/2-1} & Im Y_{M-2,N/2-1}& Im Y_{M/2-1,N/2} \\ Re Y_{M/2,0} & Re Y_{M-1,1} & Im Y_{M-1,1} &...&...& ... & Re Y_{M-1,N/2-1} & Im Y_{M-1,N/2-1}& Re Y_{M/2,N/2} \end{bmatrix}

Yes, I know about this, but I was hoping there’s some easier way than to write a rather complicated transforming function from normal matrix to CCS matrix myself. I was hoping this issue would be more common and that there is a workaround people use, other than giving up and using the slow full spectrum by COMPLEX_OUTPUT

The function mulSpectrums performs the per-element multiplication of the two CCS-packed or complex matrices that are results of a real or complex Fourier transform

so mulSpectrums should do what you need.

It probably detects the situation by checking the element type (2-channel = complex, 1-channel = CCS)

related:

Correct me if I’m wrong, but mulSpectrums doesn’t do what I need. Straight out of the source code for mulSpectrums:

CV_Assert( type == srcB.type() && srcA.size() == srcB.size() );

This is not true for my case. mulSpectrums needs either BOTH 2-channel(complex) data, which I am not interested in, or BOTH 1-channel CCS. I have one 1-channel CCS (result of DFT), and one 1-channel NOT CCS.

oh right, brain fart