├── Huffman.cpp ├── Lion.cmp.png ├── Lion.compressed ├── Lion.jpg ├── README.md ├── buildimage.cpp ├── compress.cpp ├── compression.cpp ├── histogram.cpp ├── sunset.cmp.png ├── sunset.compressed └── sunset.jpg /Huffman.cpp: -------------------------------------------------------------------------------- 1 | # include 2 | # include 3 | # include 4 | # include 5 | # include 6 | # include 7 | using namespace std; 8 | 9 | 10 | struct node{ 11 | node* leftChild; 12 | node* rightChild; 13 | int frequency; 14 | int content; 15 | string code; 16 | 17 | bool operator<(const node &a) const { return (frequency > a.frequency);} 18 | }; 19 | 20 | class Huffman 21 | { 22 | priority_queue nodeArray; 23 | vector codeTable; 24 | vector symbolTable; 25 | vector image; 26 | 27 | public: 28 | Huffman(){}; 29 | node getHuffmanTree(); 30 | void BFS(node* temproot, string s); 31 | vector getHuffmanCode(); 32 | void setFrequenceTable(vector f); 33 | void setFrequenceTable(int ind, float frequency); 34 | string encode(vector e); 35 | vector decode(string d); 36 | void searchContent(node* root, string im); 37 | virtual ~Huffman(){}; 38 | }; 39 | 40 | 41 | //Huffman::Huffman() {} 42 | 43 | //Huffman::~Huffman() {} 44 | 45 | node Huffman::getHuffmanTree() 46 | { 47 | while(!nodeArray.empty()) 48 | { 49 | node* rootNode = new node; 50 | node* leftNode = new node; 51 | node* rightNode = new node; 52 | 53 | *leftNode = nodeArray.top(); 54 | nodeArray.pop(); 55 | *rightNode = nodeArray.top(); 56 | nodeArray.pop(); 57 | 58 | rootNode->leftChild = leftNode; 59 | rootNode->rightChild = rightNode; 60 | rootNode->frequency = leftNode->frequency + rightNode->frequency; 61 | 62 | nodeArray.push(*rootNode); 63 | if(nodeArray.size() == 1) 64 | {//only the root node exsits 65 | break; 66 | } 67 | } 68 | 69 | return nodeArray.top(); 70 | } 71 | 72 | 73 | 74 | //BFS algorithm to search the symbol of the content in the tree 75 | void Huffman::BFS(node* temproot, string s) 76 | { 77 | node* root1 = new node; 78 | root1 = temproot; 79 | 80 | root1->code = s; 81 | 82 | if (root1 == NULL){} 83 | else if(root1->leftChild == NULL && root1->rightChild == NULL) 84 | { 85 | short i = root1->content; 86 | codeTable.at(i) = root1->frequency; 87 | symbolTable.at(i) = root1->code; 88 | } 89 | else{ 90 | root1->leftChild->code = s.append("0"); 91 | s.erase(s.end()-1); 92 | root1->rightChild->code = s.append("1"); 93 | s.erase(s.end()-1); 94 | 95 | BFS(root1->leftChild, s.append("0")); 96 | s.erase(s.end()-1); 97 | BFS(root1->rightChild, s.append("1")); 98 | s.erase(s.end()-1); 99 | } 100 | } 101 | 102 | 103 | 104 | 105 | //Compute and return the table of symbols 106 | vector Huffman::getHuffmanCode() 107 | { 108 | 109 | node root = getHuffmanTree();//construct the huffman tree 110 | 111 | codeTable.resize(UCHAR_MAX + 1);//Code table with 256 bins 112 | symbolTable.resize(UCHAR_MAX + 1);//Code table with 256 bins 113 | 114 | BFS(&root,"");//Search tree-basead code with BFS algorithm 115 | 116 | return codeTable;//return table of symbols 117 | } 118 | 119 | 120 | 121 | //Insert the frequency of the symbols into a priority queue 122 | void Huffman::setFrequenceTable(vector f) 123 | { 124 | 125 | for (unsigned i = 0; i < f.size(); i++) 126 | { 127 | setFrequenceTable(i, f[i]); 128 | } 129 | } 130 | 131 | 132 | 133 | void Huffman::setFrequenceTable(int ind, float frequency) 134 | { 135 | 136 | if (frequency <= 0) return; 137 | 138 | node temp; 139 | temp.frequency = frequency; 140 | temp.content = ind; 141 | temp.leftChild = NULL; 142 | temp.rightChild = NULL; 143 | nodeArray.push(temp); 144 | } 145 | 146 | 147 | 148 | string Huffman::encode(vector e) 149 | { 150 | string codifiedImage = ""; 151 | 152 | for(unsigned i = 0; i < e.size() ; i++){ 153 | if (symbolTable.at(e.at(i)) == ""){ 154 | cout << "\nError: Code don't exist in CodeTable." << endl; 155 | } 156 | codifiedImage += symbolTable.at(e.at(i)); 157 | } 158 | return codifiedImage; 159 | } 160 | 161 | 162 | 163 | vector Huffman::decode(string d) 164 | { 165 | 166 | node root = getHuffmanTree(); 167 | 168 | searchContent(&root, d); 169 | 170 | return image; 171 | } 172 | 173 | 174 | void Huffman::searchContent(node* root, string im) 175 | { 176 | node* n = new node; 177 | n = root; 178 | 179 | size_t imSize = im.length(); 180 | image.clear(); 181 | 182 | for (size_t i = 0; i <= imSize; i++) 183 | { 184 | if (n->leftChild == NULL && n->rightChild == NULL) 185 | {//leaf 186 | image.push_back(n->content); 187 | n = root; 188 | } 189 | 190 | n = (im[i] == '1') ? n->rightChild : n->leftChild; 191 | 192 | } 193 | im.clear(); 194 | } 195 | 196 | 197 | -------------------------------------------------------------------------------- /Lion.cmp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewkamble88/Image-Compression-By-Huffman-Coding/7fec17ce67ad4320f079803d5be45bf8d47c9aad/Lion.cmp.png -------------------------------------------------------------------------------- /Lion.compressed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewkamble88/Image-Compression-By-Huffman-Coding/7fec17ce67ad4320f079803d5be45bf8d47c9aad/Lion.compressed -------------------------------------------------------------------------------- /Lion.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewkamble88/Image-Compression-By-Huffman-Coding/7fec17ce67ad4320f079803d5be45bf8d47c9aad/Lion.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Image-Compression-By-Huffman-Coding 2 | Compression of image by using OpenCV library and Huffman Coding Algorithm 3 | 4 | #Data Structures and Algorithms mini project on Huffman Coding 5 | 6 | A]Commands for compiling the code in OpenCV: 7 | 8 | 1)g++ `pkg-config --cflags opencv` programName.cpp `pkg-config --libs opencv` 9 | 10 | 2)./a.out image.jpg //For giving image input from command line 11 | 12 | B]Commands for showing Histogrtam: 13 | 14 | 1)g++ histogram.cpp 15 | 16 | 2)./a.out image.jpg //For giving image input from command line 17 | -------------------------------------------------------------------------------- /buildimage.cpp: -------------------------------------------------------------------------------- 1 | # include 2 | #include "compress.cpp" 3 | 4 | int main(int argc, char** argv) 5 | { 6 | 7 | Compressor d; 8 | d.decompress(argv[1]); 9 | return 0; 10 | } 11 | 12 | 13 | -------------------------------------------------------------------------------- /compress.cpp: -------------------------------------------------------------------------------- 1 | # include "opencv2/highgui/highgui.hpp" 2 | # include "opencv2/imgproc/imgproc.hpp" 3 | # include 4 | # include 5 | # include 6 | # include 7 | # include "opencv2/highgui/highgui.hpp" 8 | # include "opencv2/imgproc/imgproc.hpp" 9 | # include 10 | # include "Huffman.cpp" 11 | using namespace std; 12 | using namespace cv; 13 | 14 | class Compressor 15 | { 16 | Huffman h; 17 | Mat grayImage;//Original image converted to monochromatic 18 | Mat dctImage;//Image DCT quantized 19 | int height, heightDCT; 20 | int width, widthDCT; 21 | float C;//Compression Param 22 | int *zigZagMask; // A mask to zig-zag search 23 | string *shiftedBit;//Mask for shift bits in string 24 | unsigned int numberBitsShifted; 25 | Mat luminance;//Quantization Matrix for luminance 26 | priority_queue frequenceTable;//Frequence table for Huffman Algorithm 27 | ofstream outfile; //To write in .compressed 28 | ifstream infile; //To read from .compressed 29 | string codifiedImage; //Image after huffman codification 30 | string fileName; //Name of the file .compressed 31 | vector codeTable; 32 | 33 | public: 34 | Compressor(); 35 | virtual ~Compressor(){}; 36 | void setParamCompression(char* imageName); 37 | void setParamDecompression(char *imageName); 38 | void forwardDCT(); // Forward transformation - DCT 39 | void inverseDCT(); // Inverse transformation - iDCT 40 | void displayImage(string imageName, Mat image);// Display all images 41 | void compress(char* imageName);//Execute Huffman to create a table of symbols and codify the image to a file 42 | void decompress(char* imageName); 43 | void searchFrequenceTable();// Search the frequency table and set it in huffman's codification. 44 | void readCodeTable(); // Read from .compressed the frequency table and set it in huffman's codification. 45 | 46 | void readCodifiedImage(); // Read the image from .compressed. 47 | }; 48 | 49 | 50 | Compressor::Compressor() 51 | { 52 | //Mask to shiftting a bit in string 53 | static string bitsMask[10] = {"", "0", "00", "000", "0000", "00000", "000000", "0000000", "00000000"}; 54 | shiftedBit = bitsMask; 55 | 56 | static int zzMask[64] = { 57 | 0, 1, 8, 16, 9, 2, 3, 10, 58 | 17, 24, 32, 25, 18, 11, 4, 5, 59 | 12, 19, 26, 33, 40, 48, 41, 34, 60 | 27, 20, 13, 6, 7, 14, 21, 28, 61 | 35, 42, 49, 56, 57, 50, 43, 36, 62 | 29, 22, 15, 23, 30, 37, 44, 51, 63 | 58, 59, 52, 45, 38, 31, 39, 46, 64 | 53, 60, 61, 54, 47, 55, 62, 63}; 65 | zigZagMask = zzMask; 66 | 67 | //Create the luminance matrix for quantization 68 | luminance = (Mat_(8, 8) << 69 | 16, 11, 10, 16, 24, 40, 51, 61, 70 | 12, 12, 14, 19, 26, 58, 60, 55, 71 | 14, 13, 16, 24, 40, 57, 69, 56, 72 | 14, 17, 22, 29, 51, 87, 80, 62, 73 | 18, 22, 37, 56, 68, 109, 103, 77, 74 | 24, 35, 55, 64, 81, 104, 113, 92, 75 | 49, 64, 78, 87, 103, 121, 120, 101, 76 | 72, 92, 95, 98, 112, 100, 103, 99); 77 | 78 | width = 0; 79 | height = 0; 80 | widthDCT = 0; 81 | heightDCT = 0; 82 | C = 1; //Compress rate - [1 Maximal - 8 Minimal] 83 | numberBitsShifted = 0; 84 | } 85 | 86 | 87 | 88 | void Compressor::setParamCompression(char* imageName){ 89 | /// Load image in gray scale 90 | grayImage = imread( imageName, IMREAD_GRAYSCALE ); 91 | 92 | //Check if image exist 93 | if( !grayImage.data ){ 94 | cout << "\nCan't load the image. Please insert the image address." << endl; 95 | throw exception(); 96 | } 97 | 98 | 99 | // Modify the image names to .compressed 100 | fileName.clear(); 101 | fileName.append(imageName); 102 | fileName.erase(fileName.end()-4, fileName.end()); 103 | fileName += ".compressed"; //sufix 104 | 105 | //Open output streams to .compressed 106 | outfile.open(fileName.c_str()); 107 | 108 | // Transform the image resolutions to a resolution with size multiple of 8 by 8 109 | // Necessary to broke the image in 8 by 8 blocks in DCT step 110 | height = grayImage.size().height; 111 | width = grayImage.size().width; 112 | 113 | heightDCT = (height%8) ? (heightDCT = 8 - height%8) : 0; 114 | widthDCT = (width%8) ? (widthDCT = 8 - width%8) : 0; 115 | 116 | if (heightDCT != 0){ 117 | Mat hBlock = grayImage(Rect(0, height-heightDCT, width, heightDCT)); 118 | vconcat(grayImage, hBlock, grayImage); 119 | height += heightDCT; 120 | } 121 | 122 | if (widthDCT != 0){ 123 | Mat wBlock = grayImage(Rect(width-widthDCT, 0, widthDCT, height)); 124 | hconcat(grayImage, wBlock, grayImage); 125 | width += widthDCT; 126 | } 127 | 128 | // Write the image's size in .compressed 129 | outfile << height << " " << width << endl; 130 | outfile << heightDCT << " " << widthDCT << endl; 131 | 132 | } 133 | 134 | 135 | // Forward transformation - DCT 136 | void Compressor::forwardDCT(){ 137 | 138 | dctImage = Mat_(height*C/8, width*C/8); 139 | 140 | for (int i = 0; i < height; i += 8){ 141 | for (int j = 0; j < width; j += 8){ 142 | // Get a block 8x8 for each position on image 143 | Mat block8 = grayImage(Rect(j, i, 8, 8)); 144 | // Convert block from 8 bits to 64 bits 145 | block8.convertTo(block8, CV_32FC1); 146 | // DCT 147 | dct(block8, block8); 148 | // Quantization step 149 | divide(block8, luminance, block8); 150 | // Adding 128 to the block 151 | add(block8, 128.0, block8); 152 | // Converting it back to unsigned char 153 | block8.convertTo(block8, CV_8UC1); 154 | // Copying the block back to the new dct image 155 | //block8.copyTo(dctImage(Rect(j, i, 8, 8))); 156 | Mat blockC = Mat_(C, C); 157 | for (int k = 0; k < (int)C*C; k++) 158 | blockC.at(k) = block8.at(zigZagMask[k]); 159 | //cout << "Copyto\n"; 160 | blockC.copyTo(dctImage(Rect(j*C/8, i*C/8, C, C))); 161 | 162 | 163 | } 164 | } 165 | dctImage.convertTo(dctImage, CV_8UC1); 166 | } 167 | 168 | 169 | 170 | void Compressor::inverseDCT(){ 171 | grayImage = Mat_(height, width); 172 | 173 | for (int i = 0; i < height*C/8; i+=C){ 174 | for (int j = 0; j < width*C/8; j+=C){ 175 | // Get a block 8x8 for each position on image 176 | Mat block = dctImage(Rect(j, i, C, C)); 177 | 178 | // Convert block from 8 bits to 64 bits 179 | block.convertTo(block, CV_32FC1); 180 | 181 | // Subtracting the block by 128 182 | subtract(block, 128, block); 183 | 184 | Mat block8 = Mat::zeros(8, 8, CV_32FC1); 185 | for (int k = 0; k < (int)C*C; k++) 186 | block8.at(zigZagMask[k]) = block.at(k); 187 | 188 | 189 | // Quantization step 190 | multiply(block8, luminance, block8); 191 | 192 | // Inverse DCT 193 | idct(block8, block8); 194 | 195 | // Converting it back to unsigned char 196 | block8.convertTo(block8, CV_8UC1); 197 | 198 | // Copying the block back to the new dct image 199 | //cout << "Copyto\n"; 200 | block8.copyTo(grayImage(Rect(8*j/C, 8*i/C, 8, 8))); 201 | } 202 | } 203 | 204 | } 205 | 206 | 207 | // Display all images 208 | void Compressor::displayImage(string imageName, Mat image){ 209 | /// Display 210 | namedWindow(imageName, CV_WINDOW_AUTOSIZE ); 211 | imshow(imageName, image); 212 | waitKey(0); 213 | } 214 | 215 | 216 | 217 | // Compute the histogram matrix for dct image in planes 218 | void Compressor::searchFrequenceTable(){ 219 | int histSize = 256; /// Establish the number of bins 220 | 221 | float range[] = {0, 256}; /// Set the ranges 222 | const float* histRange = {range}; 223 | 224 | bool uniform = true; 225 | bool accumulate = false; 226 | 227 | Mat histogram;//Histogram for DCT Image 228 | 229 | calcHist( &dctImage, 1, 0, Mat(), histogram, 1, &histSize, &histRange, uniform, accumulate); 230 | vector f(histogram.begin(), histogram.end());//Transform mat to vector 231 | h.setFrequenceTable(f); 232 | } 233 | 234 | 235 | 236 | //Compressor step 237 | void Compressor::compress(char* imageName){ 238 | //Just for information 239 | cout << "\nCompressing..."; 240 | 241 | cout << "\nSetting Parameter..."; 242 | setParamCompression(imageName); 243 | 244 | cout << "\nTransforming Image..."; 245 | forwardDCT(); 246 | 247 | cout << "\nSearching Frequency Table..."; 248 | searchFrequenceTable(); 249 | 250 | cout << "\nComputing Symbol Table..."; 251 | codeTable = h.getHuffmanCode(); 252 | 253 | //Write the Frequency Table in the file 254 | cout << "\nPrinting Frequency Table..."; 255 | for (unsigned short i = 0; i < codeTable.size(); i++){ 256 | if (codeTable.at(i) == 0) continue; 257 | outfile << i << " " << codeTable.at(i) << endl; 258 | } 259 | 260 | //transform image Mat to vector 261 | vector inputFile; 262 | inputFile.assign(dctImage.datastart, dctImage.dataend); 263 | 264 | //Codify image dct based on table of code from Huffman 265 | cout << "\nEncoding Image with Huffman..."; 266 | codifiedImage = h.encode(inputFile); 267 | 268 | //Add 0's in the end of the file to complete a byte 269 | numberBitsShifted = 8 - codifiedImage.length()%8; 270 | codifiedImage += shiftedBit[numberBitsShifted]; 271 | 272 | 273 | //End of the code table and the number of bits 0 shifted in the end of the file 274 | outfile << "#" << numberBitsShifted << endl; 275 | 276 | cout << "\nPrinting Image..."; 277 | size_t imSize = codifiedImage.size(); 278 | for (size_t i = 0; i < imSize; i += 8){ 279 | outfile << (uchar)strtol(codifiedImage.substr(i, 8).c_str(), 0, 2); 280 | } 281 | codifiedImage.clear(); 282 | 283 | //Close the file .compressed 284 | outfile.close(); 285 | 286 | //Just for information 287 | if (!codifiedImage.length()) 288 | cout << "\nCompressing Successful!"; 289 | else 290 | cout << "\nCompressing Failed!"; 291 | 292 | } 293 | 294 | 295 | void Compressor::setParamDecompression(char* imageName){ 296 | fileName.clear(); 297 | fileName.append(imageName); 298 | 299 | if (fileName.substr(fileName.length()-11, fileName.length()) != ".compressed"){ 300 | cout << "\nCan't load the image. Please insert the image address." << endl; 301 | throw exception(); 302 | } 303 | fileName.erase(fileName.length()-11, fileName.length()); 304 | fileName += ".cmp.png"; 305 | 306 | infile.open(imageName); 307 | if (!infile.is_open()){ 308 | cout << "\nCan't load the image. Please insert the image address." << endl; 309 | throw exception(); 310 | } 311 | 312 | string size;//Get the original size of the image 313 | infile >> size; 314 | height = atoi(size.c_str()); 315 | infile >> size; 316 | width = atoi(size.c_str()); 317 | 318 | infile >> size; 319 | heightDCT = atoi(size.c_str()); 320 | infile >> size; 321 | widthDCT = atoi(size.c_str()); 322 | } 323 | 324 | 325 | // Read the symbol table 326 | void Compressor::readCodeTable(){ 327 | 328 | string ind, frequency; 329 | infile >> ind; 330 | while(ind[0] != '#'){ 331 | infile >> frequency; 332 | h.setFrequenceTable(atoi(ind.c_str()), strtof(frequency.c_str(), 0)); 333 | infile >> ind; 334 | } 335 | ind.erase(0,1);//remove '#' 336 | numberBitsShifted = atol(ind.c_str()); 337 | } 338 | 339 | 340 | void Compressor::readCodifiedImage(){ 341 | unsigned char c; 342 | unsigned char mask = 128;//1000 0000 343 | //codifiedImage.clear(); 344 | 345 | int count = 0; 346 | 347 | infile >> noskipws; 348 | infile >> c; 349 | 350 | while(infile >> c){ 351 | for (int i = 0; i < 8; i++){ 352 | 353 | if ((c << i) & mask){ 354 | codifiedImage.push_back('1'); 355 | } 356 | else{ 357 | codifiedImage.push_back('0'); 358 | } 359 | count++; 360 | } 361 | } 362 | codifiedImage.erase(codifiedImage.length()-numberBitsShifted, numberBitsShifted);//remove the exceed bits 363 | } 364 | 365 | 366 | 367 | //Uncompress step 368 | void Compressor::decompress(char* fileName){ 369 | //Just for information 370 | cout << "\nUncompressing..."; 371 | 372 | cout << "\nSetting Parameters..."; 373 | setParamDecompression(fileName); 374 | 375 | cout << "\nReading Symbol Table ..."; 376 | readCodeTable(); 377 | 378 | cout << "\nsReading Codified Image ..."; 379 | readCodifiedImage(); 380 | 381 | cout << "\nDecoding Image with Huffman..."; 382 | vector dctFile = h.decode(codifiedImage); 383 | 384 | dctImage = Mat::zeros(height*C/8, width*C/8, CV_8UC1); 385 | 386 | cout << "\nTransforming Image..."; 387 | for (int i = 0; i < height*C/8; i++){ 388 | for (int j = 0; j < width*C/8; j++){ 389 | dctImage.at(i, j) = (uchar)dctFile.at(i*dctImage.step + j); 390 | } 391 | } 392 | cout << "\nProcessing Image..."; 393 | inverseDCT(); 394 | 395 | if (widthDCT != 0) 396 | grayImage = grayImage.colRange(0, width - widthDCT); 397 | 398 | if (heightDCT != 0) 399 | grayImage = grayImage.rowRange(0, height - heightDCT); 400 | 401 | //imwrite(this->fileName, grayImage); 402 | imwrite(this->fileName, grayImage); 403 | Mat testcolor=imread(this->fileName,CV_LOAD_IMAGE_COLOR); 404 | //imwrite("output.png", testcolor); 405 | cout << "\nImage Build Successfully!"; 406 | } 407 | 408 | 409 | //Compressor::~Compressor() {} 410 | 411 | 412 | void show_histogram(string const& name, Mat1b const& image) 413 | { 414 | // Set histogram bins count 415 | int bins = 256; 416 | int histSize[] = {bins}; 417 | // Set ranges for histogram bins 418 | float lranges[] = {0, 256}; 419 | const float* ranges[] = {lranges}; 420 | // create matrix for histogram 421 | Mat hist; 422 | int channels[] = {0}; 423 | 424 | // create matrix for histogram visualization 425 | int const hist_height = 256; 426 | Mat3b hist_image = Mat3b::zeros(hist_height, bins); 427 | 428 | calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges, true, false); 429 | 430 | double max_val=0; 431 | minMaxLoc(hist, 0, &max_val); 432 | 433 | // visualize each bin 434 | for(int b = 0; b < bins; b++) 435 | { 436 | float const binVal = hist.at(b); 437 | int const height = cvRound(binVal*hist_height/max_val); 438 | line 439 | ( hist_image 440 | , Point(b, hist_height-height), Point(b, hist_height) 441 | , Scalar::all(255) 442 | ); 443 | } 444 | imshow(name, hist_image); 445 | } 446 | 447 | -------------------------------------------------------------------------------- /compression.cpp: -------------------------------------------------------------------------------- 1 | # include 2 | #include 3 | #include "compress.cpp" 4 | using namespace cv; 5 | int main(int argc, char** argv) 6 | { 7 | 8 | Compressor c; 9 | c.compress(argv[1]); 10 | Mat3b image1 = imread(argv[1], 0); 11 | Mat1b image1_gray,image2; 12 | cvtColor(image1, image1_gray, COLOR_BGR2GRAY); 13 | show_histogram(argv[1], image1_gray); 14 | waitKey(); 15 | return 0; 16 | } 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /histogram.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace cv; 3 | void show_histogram(std::string const& name, Mat1b const& image) 4 | { 5 | // Set histogram bins count 6 | int bins = 256; 7 | int histSize[] = {bins}; 8 | // Set ranges for histogram bins 9 | float lranges[] = {0, 256}; 10 | const float* ranges[] = {lranges}; 11 | // create matrix for histogram 12 | Mat hist; 13 | int channels[] = {0}; 14 | 15 | // create matrix for histogram visualization 16 | int const hist_height = 256; 17 | Mat3b hist_image = Mat3b::zeros(hist_height, bins); 18 | 19 | calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges, true, false); 20 | 21 | double max_val=0; 22 | minMaxLoc(hist, 0, &max_val); 23 | 24 | // visualize each bin 25 | for(int b = 0; b < bins; b++) { 26 | float const binVal = hist.at(b); 27 | int const height = cvRound(binVal*hist_height/max_val); 28 | line 29 | ( hist_image 30 | , Point(b, hist_height-height), Point(b, hist_height) 31 | , Scalar::all(255) 32 | ); 33 | } 34 | imshow(name, hist_image); 35 | } 36 | 37 | int main (int argc, const char** argv) 38 | { 39 | // here you can use IMREAD_GRAYSCALE to load grayscale image, see image2 40 | Mat3b const image1 = imread("Lion.cmp.png", IMREAD_COLOR); 41 | Mat1b image1_gray; 42 | cvtColor(image1, image1_gray, COLOR_BGR2GRAY); 43 | //imshow("image1", image1_gray); 44 | show_histogram("image1 hist", image1_gray); 45 | 46 | /*Mat1b const image2 = imread("C:\\workspace\\bunny.jpg", IMREAD_GRAYSCALE); 47 | imshow("image2", image2); 48 | show_histogram("image2 hist", image2);*/ 49 | 50 | waitKey(); 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /sunset.cmp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewkamble88/Image-Compression-By-Huffman-Coding/7fec17ce67ad4320f079803d5be45bf8d47c9aad/sunset.cmp.png -------------------------------------------------------------------------------- /sunset.compressed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewkamble88/Image-Compression-By-Huffman-Coding/7fec17ce67ad4320f079803d5be45bf8d47c9aad/sunset.compressed -------------------------------------------------------------------------------- /sunset.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewkamble88/Image-Compression-By-Huffman-Coding/7fec17ce67ad4320f079803d5be45bf8d47c9aad/sunset.jpg --------------------------------------------------------------------------------