이진 마스크 이미지 압축률

spring·2020년 11월 9일
0

세그멘테이션 레이블링시 정보를 저장하기 위해 압축 방법들을 비교해 보았다.

  • uchar 타입으로 저장하게 되면 255개의 레이블만 인식할 수 있기에 기각.
    • (인덱스 매핑을 쓰면 완화되나, 한 이미지에 255개 이상의 레이블이 등장하면 문제가 된다.)
  • int32로 저장하게 되면 42억개의 레이블을 저장할 수 있다.
    • 클래스 수와 관계 없이 일정한 크기를 보장받는다.
    • 겹치는 문제를 해결할 수 없다.
    • 인덱스 매핑이 반드시 필요하다.
  • 이진 마스크는 클래스 수에 따라 용량이 무한정으로 증가하는 단점이 있다.

우선적으로 이진 마스크에 대한 압축률을 비교해 보았다.

(아래 포스트는 jupyter로 작성됨)

#include<iostream>
#include<string>
#include<opencv2/opencv.hpp>
#include<zlib.h>
struct LabelSegmentation {
	int width = 0;
	int height = 0;
	std::vector<uchar> data;
public:
	int Compression(const cv::Mat& in) {
		height = in.rows;
		width = in.cols;
		data.assign(height*width, 0);
		Bytef* inbyte = static_cast<Bytef*>(in.data);
		size_t insize = in.rows* in.cols;

		z_stream defstream = { 0 };
		defstream.avail_in = insize + 1;
		defstream.next_in = inbyte;
		defstream.avail_out = width*height;
		defstream.next_out = static_cast<Bytef*>(data.data());
		deflateInit(&defstream, Z_BEST_COMPRESSION);
		deflate(&defstream, Z_FINISH);
		deflateEnd(&defstream);
		data.resize(defstream.total_out);
        return defstream.total_out;
	}
	cv::Mat Decompression() {
		cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1);
		z_stream infstream = { 0 };
		infstream.avail_in = data.size();
		infstream.next_in = static_cast<Bytef*>(data.data());
		infstream.avail_out = height*width;
		infstream.next_out = static_cast<Bytef*>(out.data);
		inflateInit(&infstream);
		inflate(&infstream, Z_NO_FLUSH);
		inflateEnd(&infstream);
		return out;
	}
};
std::vector<int> RLE(const cv::Mat& mask) {
	std::vector<int> rle;
	rle.push_back(mask.rows);
	rle.push_back(mask.cols);
	auto it = mask.begin<uchar>();
	int e = 1;
	int b = *it > 0 ? 1 : -1;
	it++;
	while (it != mask.end<uchar>()) {
		int p = *it > 0 ? 1 : -1;
		if (p == b)e++;
		else {
			rle.push_back(e*b);
			b = p;
			e = 1;
		}
		it++;;
	}
	rle.push_back(e*b);
	return rle;
}
void image_show(cv::Mat img,std::string name,int width=384){
    cv::Mat img2;
    cv::resize(img,img2,cv::Size(width,img.rows*width/img.cols));
    cv::imshow(name,img2);
}
#define MeasureTime(RET,EXPRESSION,NAME)    do{\
    auto t = cv::getTickCount();\
    RET = EXPRESSION;\
    std::cout << NAME << ": " << (cv::getTickCount() - t) / cv::getTickFrequency() << std::endl;\
    }while(0)
std::vector<std::string> urls={
    "https://i.stack.imgur.com/5vb9J.png",
    "https://i.stack.imgur.com/Ga5Pe.png",
    "https://i.stack.imgur.com/nm2HM.png",
    "https://cs-people.bu.edu/sidmys/cs585/A2/binary_mask/skintone_mask.png"};
for(auto& url:urls){
    std::cout << url << std::endl;
    cv::Mat img=cv::imread(url.c_str());
    cv::cvtColor(img, img, cv::COLOR_BGR2GRAY);
    cv::threshold(img, img, 1, 255, cv::THRESH_BINARY);
    std::cout << "width: " << img.cols << "\t" << "height: " << img.rows << std::endl;
    image_show(img,"image");
	LabelSegmentation lbl;
    
	MeasureTime(int dummy,lbl.Compression(img),"Time(Deflate)");
    
    std::vector<int> rle;
    MeasureTime(rle,RLE(img),"Time(RLE)");
    
    std::vector<uchar> pngbuf;
    MeasureTime(bool dummy,cv::imencode(".png",img, pngbuf),"Time(PNG)");
    
    std::cout << "RLE: " << rle.size() * 4 << std::endl;
	std::cout << "Deflate: " << lbl.data.size() + 8 << std::endl;
    std::cout << "PNG: " << pngbuf.size() << std::endl;
    
    for(int t=0;t<100;t++)std::cout<< "-";std::cout << std::endl;
}

https://i.stack.imgur.com/5vb9J.png
width: 1024 height: 768
image

Time(Deflate): 0.0119147
Time(RLE): 0.575732
Time(PNG): 0.00367758
RLE: 3644
Deflate: 1944
PNG: 4141


https://i.stack.imgur.com/Ga5Pe.png
width: 512 height: 512
image

Time(Deflate): 0.0143451
Time(RLE): 0.202859
Time(PNG): 0.0016504
RLE: 3948
Deflate: 1460
PNG: 3046


https://i.stack.imgur.com/nm2HM.png
width: 488 height: 275
image

Time(Deflate): 0.0263108
Time(RLE): 0.0985578
Time(PNG): 0.000986006
RLE: 8588
Deflate: 2227
PNG: 3950


https://cs-people.bu.edu/sidmys/cs585/A2/binary_mask/skintone_mask.png
width: 990 height: 557
image

Time(Deflate): 0.0784132
Time(RLE): 0.437506
Time(PNG): 0.00400376
RLE: 28924
Deflate: 8070
PNG: 11730


profile
Researcher & Developer @ NAVER Corp | Designer @ HONGIK Univ.

0개의 댓글