![b8c438490a4b8e7a55e7e59b22f892c9.png](https://i-blog.csdnimg.cn/blog_migrate/45de0eeb42e25076ef489dea06ac09e1.jpeg)
前言
openCV处理的图像最小的位深度都是8,即每个像素的灰度值要用8bit存储,二值化处理的图像也是用8bit来存储每个像素的灰度值(0代表黑色,255代表白色),为什么不能用0和1表示呢,即每个像素用1bit存储。这样保存的图像占用的存储空间更小,在某些场合下会发挥重大的作用,下面直接上代码,将位深8bit的图像保存为位深1bit图像。
代码实现
将位深8bit的图像Mat img转化为位深1bit图像数据。
int 8Bit2Binary(const cv::Mat img, int line_byte, char * data)
{
int width = img.cols;
int height = img.rows;
size_t line_size = line_byte * 8;
size_t bit_size = line_size * height;
char *p = data; int offset, v; unsigned char temp;
for (int row = height - 1; row >= 0; row--)
{
for (int col = 0; col < width; col++)
{
offset = col % 8;
v = img.data[row * width + col];
temp = 1;
temp = temp << (8 - offset - 1);
if (v == 255)
{
*(p + col / 8) |= temp;
}
else
{
temp = ~temp;
*(p + col / 8) &= temp;
}
}
for (int j = width / 8; j < line_byte; j++)
p[j] = 0;
p = p + line_byte;
}
return 0;
}
将位深8bit的图像保存为位深1bit图像。
int save1BitImage(const cv::Mat img, std::string dst)
{
int width = img.cols;
int height = img.rows;
const int biBitCount = 1;
//颜色表大小,以字节为单位,灰度图像颜色表为256*4字节,彩色图像颜色表大小为0,二值图为2*4
int color_type_num = 2;
int colorTablesize = color_type_num * sizeof(RGBQUAD);
RGBQUAD *pColorTable = new RGBQUAD[color_type_num];
for (int i = 0; i < color_type_num; i++) {
pColorTable[i].rgbBlue = i * 255;
pColorTable[i].rgbRed = i * 255;
pColorTable[i].rgbGreen = i * 255;
pColorTable[i].rgbReserved = 0;
}
//待存储图像数据每行字节数为4的倍数
int line_byte = (width * biBitCount >> 3 + 3) / 4 * 4;
char * p_data = (char *)malloc(line_byte*height);
//统计算法执行时间
double start = static_cast<double>(cv::getTickCount());
8Bit2Binary(img, line_byte, p_data);
//统计算法运行时间
double end = static_cast<double>(cv::getTickCount());
double run_time = (end - start) / cv::getTickFrequency();
std::cout << "Run Time1:" << run_time * 1000 << "ms" << std::endl;
std::ofstream fp(dst.c_str(), std::ios::binary | std::ios::out);
if (!fp.is_open()) {
// cout << "open " << dst << " failed!" << endl;
return -1;
}
//申请位图文件头结构变量,填写文件头信息
BITMAPFILEHEADER fileHead;
fileHead.bfType = 0x4D42; //bmp类型
fileHead.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
+ colorTablesize + line_byte*height; //bfSize是图像文件4个组成部分之和
fileHead.bfReserved1 = 0;
fileHead.bfReserved2 = 0;
fileHead.bfOffBits = 54 + colorTablesize; //bfOffBits是图像文件前3个部分所需空间之和
fp.write((char *)&fileHead, sizeof(BITMAPFILEHEADER)); //写文件头进文件
//申请位图信息头结构变量,填写信息头信息
BITMAPINFOHEADER head;
head.biBitCount = biBitCount;
head.biClrImportant = 0;
head.biClrUsed = 0;
head.biCompression = 0;
head.biHeight = height;
head.biPlanes = 1;
head.biSize = 40;
head.biSizeImage = line_byte*height;
head.biWidth = width;
head.biXPelsPerMeter = 0;
head.biYPelsPerMeter = 0;
//写位图信息头进内存
fp.write((char *)&head, sizeof(BITMAPINFOHEADER));
//颜色表,写入文件
fp.write((char *)pColorTable, sizeof(RGBQUAD)*color_type_num);
//写位图数据进文件pBmpBuf
fp.write((char *)p_data, height*line_byte);
fp.close();
delete[]pColorTable;
delete[]p_data;
return 0;
}
测试效果
//测试8bit转1bit图像
void test_8Bit2OneBit()
{
Mat src = imread(".test.bmp", 0);//加载图像
string dst = ".result.bmp";//存放生成1位位图的路径
int a;
//统计算法执行时间
double start = static_cast<double>(cv::getTickCount());
a = save1BitImage(src, dst);
//统计算法运行时间
double end = static_cast<double>(cv::getTickCount());
double run_time = (end - start) / cv::getTickFrequency();
std::cout << "Run Time:" << run_time * 1000 << "ms" << std::endl;
system("pause");
}
最后
如果觉得文章对您有帮助的话,别忘了给我个赞,谢谢!,顺便推荐OpenCV学习资料!!!