Вычисление DCT с помощью OpenCV

#python #opencv #computer-vision #signal-processing

#python #opencv #компьютерное зрение #обработка сигналов

Вопрос:

Я пытаюсь использовать функцию dct () в OpenCV для вычисления дискретного косинусного преобразования, но получаю странные результаты.

Мой скрипт:

 import os, sys
import cv, cv2
import numpy as np

fn1 = 'original.jpg'
img1 = cv2.imread(fn1, cv2.CV_LOAD_IMAGE_GRAYSCALE)

h, w = img1.shape[:2]
vis0 = np.zeros((h,w), np.float32)
vis0[:h, :w] = img1
vis1 = cv2.dct(vis0)
img2 = cv.CreateMat(vis1.shape[0], vis1.shape[1], cv.CV_32FC3)
cv.CvtColor(cv.fromarray(vis1), img2, cv.CV_GRAY2BGR)

cv.ShowImage('',img2)
cv2.waitKey()
cv.SaveImage('saved.jpg', img2)
  

Кажется, что это выполняется без ошибок, но изображение, показанное ShowImage (), и изображение, сохраненное SaveImage (), выглядят очень разными. К сожалению, я не могу найти никаких образцов изображений, обработанных DCT, поэтому я не уверен, какое из них, если вообще какое-либо, правильное.

Исходное изображение: оригинал

Показанное изображение DCT: показано

Сохраненный образ DCT: сохранено

Почему существует такая разница между показанным и сохраненным изображениями DCT? Что правильно?

Комментарии:

1. Просто предположение, но сохраненный DCT, на мой взгляд, правильный, а показанный DCT выглядит так, как будто он каким-то образом потерял большую часть информации (как будто все пиксели> эпсилон по какой-то причине были сопоставлены с 1). Возможно, сохраненное изображение находится в диапазоне 0-255, и показанное изображение ошибочно обрезало его до 0-1.

Ответ №1:

Кажется, вы отобразили сложный вывод DCT. И, поскольку вы пытались сохранить 2-канальное изображение (DCT выводит 2 канала — один для реальной, один для мнимой части), он сохранил только реальную часть (которая каким-то образом близка к величине).

Итак, из вашего вывода DCT используйте функции magnitude () и phase () для извлечения полезной информации. Отображать их отдельно,

И, самое главное, внимательно прочитайте о DCT ( http://en.wikipedia.org/wiki/Discrete_cosine_transform ) итак, вы знаете, что делаете.

Комментарии:

1. Откуда вы получаете информацию о выходе DCT ()? То, что написано в Википедии, и то, что реализовано на самом деле, обычно очень разные вещи. Все документы OpenCV, которые я нашел, и даже мой опубликованный код показывают, что он возвращает ту же форму, что и входной массив, который для изображения в оттенках серого будет одним каналом, а не двумя. opencv.willowgarage.com/documentation/cpp /…

2. Найдите opencv refman, который поставляется с дистрибутивом. Это называется opencv.pdf или opencv_refman.pdf, в зависимости от используемой вами версии. Это более подробно, чем онлайн-ссылка. И та же форма не равна тому же номеру канала. попробуйте cout << matDct.channels(); чтобы разрешить загадку 🙂

3. Но я использовал его, и он дает мне двухканальные данные с плавающей запятой одинарной точности. Как указано в refman

4. @vasile… Я не знаю, что вам сказать. Код не лжет, и cv2.dct() выводит numpy ndarray … который не имеет функции channels(). Обратите внимание, я использую оболочку Python 2.3 (как cv, так и cv2), а не C API. Возможно, недавняя оболочка Python работает иначе, чем то, к чему вы привыкли в прошлом?

5. Я не использую python, но я использовал больше версий ocv, включая 2.3 и 2.3.1. и опубликованные вами изображения ясно показывают, что существуют сложная (первая) и реальная (вторая) части DCT. вызовите magnitude() для вывода DCT и проверьте результат. Я должен быть близок ко второму изображению (но не идентичен).

Ответ №2:

сохраненное изображение фактически такое же, но значения привязаны к [0 ..255] и преобразованы в байт (numpy.uint8) перед сохранением в формате JPEG. отрицательные значения устанавливаются равными нулю, а значения выше 255 устанавливаются равными 255.

 cv2.imshow("before_save", vis1)
vis1[vis1>255] = 255
vis1[vis1<0] = 0
cv2.imshow("saved", vis1.astype(np.uint8))