0

I'm trying to implement a DCT code in Android. I'm testing out using the code but just changing to DCT instead of DFT : Convert OpenCv DFT example from C++ to Android. There have been changes to the code, thanks to timegalore. Now I'm having problems converting the image back to BGR.

public void transformImage(){
image = Highgui.imread(imageName, Highgui.CV_LOAD_IMAGE_GRAYSCALE);      
try {
    secondImage = new Mat(image.rows(), image.cols(), CvType.CV_64FC1);
    image.convertTo(secondImage, CvType.CV_64FC1);

    int m = Core.getOptimalDFTSize(image.rows());
    int n = Core.getOptimalDFTSize(image.cols()); // on the border add zero values

    Mat padded = new Mat(new Size(n, m), CvType.CV_64FC1); // expand input image to optimal size

    Imgproc.copyMakeBorder(secondImage, padded, 0, m - secondImage.rows(), 0, n - secondImage.cols(), Imgproc.BORDER_CONSTANT);

    Mat result = new Mat(padded.size(), padded.type());
    Core.dct(padded, result);

    Mat transformedImage = new Mat(padded.size(), padded.type());
    Core.idct(result, watermarkedImage);

    completedImage = new Mat(image.rows(), image.cols(), CvType.CV_64FC1);
    Imgproc.cvtColor(transformedImage, completedImage, Imgproc.COLOR_GRAY2BGR);

} catch (Exception e) {
    Log.e("Blargh", e.toString());
}

}

Now, I have obtained this error

04-09 21:35:52.362: E/cv::error()(23460): OpenCV Error: Assertion failed (depth == CV_8U || depth == CV_16U || depth == CV_32F) in void cv::cvtColor(cv::InputArray, cv::OutputArray, int, int), file /home/reports/ci/slave_desktop/50-SDK/opencv/modules/imgproc/src/color.cpp, line 3642

I am not sure what I should do, please advise. Your help is very much appreciated!

Community
  • 1
  • 1
yukilynn
  • 15
  • 1
  • 8

1 Answers1

1

You have this line:

image.convertTo(secondImage, CvType.CV_64FC1);

but then you don't use secondImage again, just image. Try:

Imgproc.copyMakeBorder(secondImage, padded, 0, m - secondImage.rows(), 0, n - secondImage.cols(), Imgproc.BORDER_CONSTANT);

and see how you get on.

Also DCT looks like it only works on reals not complex numbers like DFT and so you don't need to add a second channel to zero the imaginary part. You can work directly with the padded variable, so:

Mat result = new Mat(padded.size(), padded.type());

then

Core.dct(padded, result);

also, the original image needs to be single channel - so a greyscale. When you call Highgui.imread the image that will be loaded is multichannel - on my device it is 3 channel in BGR format. You can convert it to greyscale using Imgproc.cvtColor but it would be simpler just to load it as grey scale in the first place:

image = Highgui.imread(imageName, Highgui.CV_LOAD_IMAGE_GRAYSCALE); 
timegalore
  • 731
  • 7
  • 9
  • haha thanks for noticing that. but it throws me this exception now : Assertion failed (type == CV_32FC1 || type == CV_64FC1) in void cv::dct(cv::InputArray, cv::OutputArray, int), file /home/reports/ci/slave_desktop/50-SDK/opencv/modules/core/src/dxt.cpp, line 2281 I would assume the cvType is wrong right? – yukilynn Apr 08 '14 at 01:37
  • thanks for the update. but I am still getting this : Assertion failed (type == CV_32FC1 || type == CV_64FC1) in void cv::dct(cv::InputArray, cv::OutputArray, int), file /home/reports/ci/slave_desktop/50-SDK/opencv/modules/core/src/dxt.cpp, line 2281. What do I need to do to fix it? – yukilynn Apr 08 '14 at 15:09
  • I've added some further info to the end of the original answer - see how you get on. – timegalore Apr 08 '14 at 20:14
  • oh I see. thanks, I will try it out. is it possible if I want to convert the image back to BGR format? – yukilynn Apr 09 '14 at 02:12
  • Oh yes, it works! Thank you so much! Would the process of idct be the same as this? – yukilynn Apr 09 '14 at 02:32
  • Yes, I don't see why not. You can also call dct with the Core.DCT_INVERSE flag, which has the same effect. Good luck with your project - glad I could help. – timegalore Apr 09 '14 at 07:13
  • thank you so much for spending your time helping me. if there is any questions, I might ask it over here again. thanks again! – yukilynn Apr 09 '14 at 09:44
  • I used cvtColor to convert back the image, but I got this error when changing back to BGR format - Assertion failed (depth == CV_8U || depth == CV_16U || depth == CV_32F) in void cv::cvtColor(cv::InputArray, cv::OutputArray, int, int), file /home/reports/ci/slave_desktop/50-SDK/opencv/modules/imgproc/src/color.cpp, line 3642. I'll edit the code to show what I've done – yukilynn Apr 09 '14 at 13:39
  • The results of idct will be a 64 bit floating point number. To visualise this you will need to normalise it to numbers in the range 0 to 255. Also, note that as the results are in greyscale converting to BGR form will still be grey but if you need a 3 channel result then fine. The normalisation process can be seen in the "Convert OpenCv DFT example from C++ to Android" thread. – timegalore Apr 09 '14 at 21:31
  • so there is no other way to get back the image to it's original BGR colour? – yukilynn Apr 10 '14 at 09:16
  • You could apply the process to each B, G and R channel individually and recombine into one image at the end. – timegalore Apr 10 '14 at 09:18
  • how do i obtain each channel's value? – yukilynn Apr 10 '14 at 09:19
  • use Core.split and then Core.merge to combine back again. – timegalore Apr 10 '14 at 09:22
  • I got this trying that out. haha. Fatal signal 11 (SIGSEGV) at 0x00000015 (code=1) – yukilynn Apr 10 '14 at 09:32
  • probably best to ask a new question with the code extract and we can look at that problem separately – timegalore Apr 10 '14 at 09:37
  • I've posted up a new question : http://stackoverflow.com/questions/22984465/fatal-signal-11-sigsegv-at-0x00000015-code-1-when-implementing-split-and-mer – yukilynn Apr 10 '14 at 09:49