Advertisement
Guest User

Untitled

a guest
Mar 30th, 2017
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.47 KB | None | 0 0
  1. #include <iostream>
  2. #define _USE_MATH_DEFINES
  3. #include <cmath>
  4. #include <opencv2/highgui/highgui.hpp>
  5.  
  6. // Velikost bloku bude 8x8 pixelu
  7. static const int N = 8;
  8.  
  9.  
  10. // JPEG kvantizacni matice
  11. static double coeffsQ[] = {
  12.         16,  11,  10,  16,  24,  40,  51,  61,
  13.         12,  12,  14,  19,  26,  58,  60,  55,
  14.         14,  13,  16,  24,  40,  57,  69,  56,
  15.         14,  17,  22,  29,  51,  87,  80,  62,
  16.         18,  22,  37,  56,  68, 109, 103,  77,
  17.         24,  35,  55,  64,  81, 104, 113,  92,
  18.         49,  64,  78,  87, 103, 121, 120, 101,
  19.         72,  92,  95,  98, 112, 100, 103,  99
  20.     };
  21.  
  22. /**
  23.  * Dopredna 2D DCT
  24.  */
  25. static void fdct2D(const cv::Mat &src, cv::Mat &dst) {
  26.     for (unsigned short v = 0; v < N; v++) {
  27.         for (unsigned short u = 0; u < N; u++) {
  28.             double g = 0;
  29.             //u dimenze
  30.             double au = (u == 0) ? 1.0 / sqrt(N) : sqrt(2.0 / N);
  31.             //v dimenze
  32.             double av =  (v == 0) ? 1.0 / sqrt(N) : sqrt(2.0 / N);
  33.  
  34.             for (unsigned short y = 0; y < N; y++) {
  35.                 for (unsigned short x = 0; x < N; x++) {
  36.                     g += src.at<double>(y, x) * au * av * cos((M_PI / N) * (x + 0.5) * u) * cos((M_PI / N) * (y + .5) * v);
  37.                 }
  38.             dst.at<double>(v, u) = g;
  39.             }
  40.         }
  41.     }
  42.  
  43.     // OpenCV DCT - ZAKOMENTOVAT!
  44.     //cv::dct(src, dst);
  45. }
  46.  
  47. /**
  48.  * Zpetna 2D DCT
  49.  */
  50. static void idct2D(const cv::Mat &src, cv::Mat &dst) {
  51.    for (unsigned short y = 0; y < N; y++) {
  52.         for (unsigned short x = 0; x < N; x++) {
  53.             double f = 0;
  54.             for (unsigned short v = 0; v < N; v++) {
  55.                 for (unsigned short u = 0; u < N; u++) {
  56.                     //u dimenze
  57.                     double au = (u == 0) ? 1.0 / sqrt(N) : sqrt(2.0 / N);
  58.                     //v dimenze
  59.                     double av =  (v == 0) ? 1.0 / sqrt(N) : sqrt(2.0 / N);
  60.                     f += au * av * src.at<double>(v, u) * cos((M_PI / N) * (x + .5) * u) * cos((M_PI / N) * (y + .5) * v);
  61.                 }
  62.             dst.at<double>(y, x) = f;
  63.             }
  64.         }
  65.     }
  66.  
  67.     // OpenCV inverzni DCT - ZAKOMENTOVAT!
  68.     //cv::dct(src, dst, cv::DCT_INVERSE);
  69. }
  70.  
  71. /**
  72.  * Kvantizace koeficientu
  73.  */
  74. static void quantize(const cv::Mat &src, cv::Mat &dst) {
  75.  
  76.     // Zadna kvantizace
  77.     //src.copyTo(dst);
  78.     double quantize;
  79.     for (unsigned short i = 0; i < N; i++) {
  80.         for (unsigned short j = 0; j < N; j++) {
  81.             quantize = round(src.at<double>(i, j) / coeffsQ[(i*N)+j]);
  82.             //dekvantizace
  83.             dst.at<double>(i, j) =  quantize * coeffsQ[(i*N)+j];
  84.             std::cout << dst.at<double>(i, j) << std::endl;
  85.         }
  86.     }
  87. }
  88.  
  89. /**
  90.  * Demonstrace komprese obrazu pomoci DCT
  91.  */
  92. static void demo(const cv::Mat &input) {
  93.     // Sem se ulozi koeficienty DCT
  94.     cv::Mat coeff(input.rows, input.cols, cv::DataType<double>::type);
  95.  
  96.     // Sem se ulozi koeficienty po provedeni kvantizace
  97.     cv::Mat quant(input.rows, input.cols, cv::DataType<double>::type);
  98.  
  99.     // Tady bude dekodovany obrazek
  100.     cv::Mat decod(input.rows, input.cols, cv::DataType<double>::type);
  101.  
  102.     // Zpracujeme obraz po blocich
  103.     for (int y = 0; y < input.rows; y += N) {
  104.         for (int x = 0; x < input.cols; x += N) {
  105.             // Aktualni zpracovavany blok bude tento vyrez celeho obrazu
  106.             cv::Rect rect(x, y, N, N);
  107.  
  108.             // Pomocne promenne, ktere reprezentuji prislusny vyrez
  109.             cv::Mat inputBlock(input, rect);
  110.             cv::Mat coeffBlock(coeff, rect);
  111.             cv::Mat quantBlock(quant, rect);
  112.             cv::Mat decodBlock(decod, rect);
  113.  
  114.             // Nejprve transformujeme blok obrazku na koeficienty pomoci DCT
  115.             fdct2D(inputBlock, coeffBlock);
  116.  
  117.             // Pak provedeme kvantizaci techto koeficientu (ztrata informace, komprese)
  118.             quantize(coeffBlock, quantBlock);
  119.  
  120.             // Z kvantovanych koeficientu zrekonstruujeme puvodni blok obrazu
  121.             idct2D(quantBlock, decodBlock);
  122.         }
  123.     }
  124.  
  125.     // Cely postup zobrazime
  126.     imshow("input",      cv::Mat_<uchar>(input));
  127.     imshow("transform",  cv::abs(coeff / 15));
  128.     imshow("quantized",  cv::abs(quant / 15));
  129.     imshow("decoded",    cv::Mat_<uchar>(decod));
  130.     imshow("difference", cv::Mat_<uchar>(cv::Mat(cv::abs(input-decod))));
  131. }
  132.  
  133. int main(int argc, char **argv) {
  134.     const char *imagename;
  135.     imagename = argc > 1 ? argv[1] : "lenna.png";
  136.  
  137.     std::cout << "Loading " << imagename << std::endl;
  138.  
  139.     // Nacteni obrazku
  140.     cv::Mat img = cv::Mat_<double>(cv::imread(imagename, CV_LOAD_IMAGE_GRAYSCALE));
  141.     if (!img.data) {
  142.         std::cerr << "Failed do load image" << std::endl;
  143.         return -1;
  144.     }
  145.  
  146.     // Spusteni dema
  147.     demo(img);
  148.  
  149.     cv::waitKey();
  150.  
  151.     return 0;
  152. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement