Uživatelské nástroje

Nástroje pro tento web


pitel:mul:cv4

Komprese JPEG – nastavení koeficientů DCT

Discrete cosine transform

zadani.cpp
#include <iostream>
#define _USE_MATH_DEFINES
#include <cmath>
#include <cv.h>
#include <highgui.h>
 
using namespace std;
using namespace cv;
 
/**
 * velikost bloku bude 8x8 pixelu
 */
static const unsigned short N = 8;
 
/**
 * dopredna 2D DCT
 */
static void fdct2D (const Mat& src, Mat& dst) {
	for (unsigned short v = 0; v < N; v++) {
		for (unsigned short u = 0; u < N; u++) {
			double g = 0;
			double au = sqrt(2.0 / N);
			if (u == 0) au = sqrt(1.0 / N);
			double av = sqrt(2.0 / N);
			if (v == 0) av = sqrt(1.0 / N);
			for (unsigned short y = 0; y < N; y++) {
				for (unsigned short x = 0; x < N; x++) {
					g += au * av * src.at<double>(y, x) * cos((M_PI / N) * (x + .5) * u) * cos((M_PI / N) * (y + .5) * v);
				}
			dst.at<double>(v, u) = g;
			}
		}
	}
}
 
/**
 * zpetna 2D DCT
 */
static void idct2D (const Mat& src, Mat& dst) {
	for (unsigned short y = 0; y < N; y++) {
		for (unsigned short x = 0; x < N; x++) {
			double f = 0;
			for (unsigned short v = 0; v < N; v++) {
				for (unsigned short u = 0; u < N; u++) {
					double au = sqrt(2.0 / N);
					if (u == 0) au = sqrt(1.0 / N);
					double av = sqrt(2.0 / N);
					if (v == 0) av = sqrt(1.0 / N);
					f += au * av * src.at<double>(v, u) * cos((M_PI / N) * (x + .5) * u) * cos((M_PI / N) * (y + .5) * v);
				}
			dst.at<double>(y, x) = f;
			}
		}
	}
}
 
/**
 * kvantizace koeficientu
 */
static void quantize (const Mat& src, Mat& dst) {
	const unsigned short Q[N][N] = {
		{16, 11, 10, 16,  24,  40,  51,  61},
		{12, 12, 14, 19,  26,  58,  60,  55},
		{14, 13, 16, 24,  40,  57,  69,  56},
		{14, 17, 22, 29,  51,  87,  80,  62},
		{18, 22, 37, 56,  68, 109, 103,  77},
		{24, 35, 55, 64,  81, 104, 113,  92},
		{49, 64, 78, 87, 103, 121, 120, 101},
		{72, 92, 95, 98, 112, 100, 103,  99}};
	for (unsigned short i = 0; i < N; i++) {
		for (unsigned short j = 0; j < N; j++) {
			//dst.at<double>(i, j) = src.at<double>(2, 2);
			dst.at<double>(i, j) = round(src.at<double>(i, j) / Q[i][j]) * Q[i][j];
		}
	}
}
 
/**
 * demonstrace komprese obrazu pomoci DCT
 */
static void demo (const Mat &input)
{
	// sem se ulozi koeficienty DCT
	Mat coeff (input.rows, input.cols, DataType<double>::type);
 
	// sem se ulozi koeficienty po provedeni kvantizace
	Mat quant (input.rows, input.cols, DataType<double>::type);
 
	// a tady bude dekodovany obrazek
	Mat decod (input.rows, input.cols, DataType<double>::type);
 
	// zpracujeme obraz po blocich
	for (int y = 0; y < input.rows; y+=N)
		for (int x = 0; x < input.cols; x+=N)
		{
			// aktualni zpracovavany blok bude tento vyrez celeho obrazu
			Rect rect (x, y, N, N);
 
			// pomocne promenne, ktere reprezentuji prislusny vyrez
			Mat inputBlock (input, rect);
			Mat coeffBlock (coeff, rect);
			Mat quantBlock (quant, rect);
			Mat decodBlock (decod, rect);
 
			// nejprve transformujeme blok obrazku na koeficienty pomoci DCT
			fdct2D (inputBlock, coeffBlock);
 
			// pak provedeme kvantizaci techto koeficientu (ztrata informace, komprese)
			quantize (coeffBlock, quantBlock);
 
			// z kvantovanych koeficientu zrekonstruujeme puvodni blok obrazu
			idct2D (quantBlock, decodBlock);
		}
 
	// cely postup zobrazit
	imshow ("input",      Mat_<uchar> (input) );
	imshow ("transform",  abs (coeff/15) );
	imshow ("quantized",  abs (quant/15) );
	imshow ("decoded",    Mat_<uchar> (decod) );
	imshow ("difference", Mat_<uchar> ( abs (input-decod) ) );
}
 
int main (int argc, char **argv)
{
	const char *imagename = argc > 1
		? argv[1] : "Lenna.png";
 
	cout << "Loading " << imagename << endl;
 
	Mat img = Mat_<double> ( imread (imagename, CV_LOAD_IMAGE_GRAYSCALE) );
	if (!img.data)
		return -1;
 
	demo (img);
 
	waitKey ();
 
	return 0;
}
/var/www/wiki/data/pages/pitel/mul/cv4.txt · Poslední úprava: 30. 12. 2022, 13.43:01 autor: 127.0.0.1