From 7f6d765d28461fb5a04da7bf8a1066a3eb4b70a0 Mon Sep 17 00:00:00 2001 From: zcy <290198252@qq.com> Date: Wed, 18 May 2022 02:28:56 +0800 Subject: [PATCH] no message --- client/webrtc_capture/src/cvhelper.cpp | 162 +++++++++++++++++++++++++ client/webrtc_capture/src/cvhelper.h | 17 +++ 2 files changed, 179 insertions(+) create mode 100644 client/webrtc_capture/src/cvhelper.cpp create mode 100644 client/webrtc_capture/src/cvhelper.h diff --git a/client/webrtc_capture/src/cvhelper.cpp b/client/webrtc_capture/src/cvhelper.cpp new file mode 100644 index 0000000..2eec1db --- /dev/null +++ b/client/webrtc_capture/src/cvhelper.cpp @@ -0,0 +1,162 @@ +#include +#include "cvhelper.h" + +#include +#include + +/* +* 将一幅RGB图像转换YCrCb图像,并得到三个分离的通道。 +*/ +void TransferRGB2YCrCb(cv::Mat &input, std::vector &chls) +{ + //YCrCb色彩空间:Y为颜色的亮度(luma)成分、而CB和CR则为蓝色和红色的浓度偏移量成分。 + //只有Y成分的图基本等同于彩色图像的灰度图。 + cv::cvtColor(input, input, cv::COLOR_BGR2YCrCb); + cv::split(input, chls); +} + +/* +* 将Y、Cr、Cb三个分离的通道合并为YCrCb图像,再转换为RGB图像。 +*/ +void MergeYCrCb2RGB(cv::Mat &output, std::vector &chls) +{ + cv::merge(chls, output); + cv::cvtColor(output, output, cv::COLOR_YCrCb2BGR); +} + + +/* +*CLAHE. +*@ClipLimit:直方图的柱子高度大于计算后的ClipLimit的部分被裁剪掉,然后将其平均分配给整张直方图,从而提升*整个图像。 +*但是本人觉得这里解释的不对,更像是累计概率分布函数的斜率上限阈值,高于ClipLimit的部分被裁剪掉, +*然后将其平均分配给整张直方图,从而提升整个图像。 +*@TilesGridSize:// 将图像分为TilesGridSize*TilesGridSize大小的方块.。(滑动窗口大小为TilesGridSize*TilesGridSize) +*/ +cv::Mat clahe_deal(cv::Mat &src, double ClipLimit = 40.0, int TilesGridSize = 8) +{ + cv::Mat ycrcb = src.clone(); + std::vector channels; + +// TransferRGB2YCrCb(ycrcb, channels); + +// cv::Mat clahe_img; +// //opencv源码中原型: createCLAHE(double clipLimit = 40.0, Size tileGridSize = Size(8, 8)); +// cv::Ptr clahe = cv::createCLAHE(); + +// clahe->setClipLimit(ClipLimit); +// clahe->setTilesGridSize(Size(TilesGridSize, TilesGridSize)); +// clahe->apply(channels[0], clahe_img); +// channels[0].release(); +// clahe_img.copyTo(channels[0]); +// MergeYCrCb2RGB(ycrcb, channels); +// return ycrcb; + return ycrcb; +} + + +//将mat数组转换为二进制,255用1表示,0用0表示 +int Mat2Binary(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]; + v = img.at(row, col); + temp = 1; + temp = temp << (8 - offset - 1); + if (v == 255) + { + *(p + col / 8) |= temp; + } + else + { + temp = ~temp; + *(p + col / 8) &= temp; + } + } + //注释掉一下代码,列数否则不能被4整除的图像最后4列会出现黑边 +/* for (int j = width / 8; j < line_byte + 1; j++) { + p[j] = 0; + } */ + p = p + line_byte; + } + return 0; +} + +//将Mat图像保存为1位bmp图 +int Save1BitImage(const cv::Mat img, std::string dst) +{ + int width = img.cols; + int height = img.rows; + const int biBitCount = 1; + + //待存储图像数据每行字节数为4的倍数,计算位图每行占多少个字节 + //int line_byte = (width * biBitCount >> 3 + 3) / 4 * 4; + int line_byte = (width * biBitCount / 8 + 5) / 4 * 4;//+3改为+5,否则无法向上对齐,造成崩溃 + char* p_data = (char*)malloc(line_byte * height + 1);//后面加1否则会报heap错误 + //memset(p_data, 0x01, line_byte * height+1); + + //将mat数组转换为二进制,255用1表示,0用0表示 + Mat2Binary(img, line_byte, p_data); + + //bmp位图颜色表大小,以字节为单位,灰度图像颜色表为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; + } + //申请位图文件头结构变量,填写文件头信息 + BITMAPFILEHEADER fileHead; + fileHead.bfType = 0x4D42; //bmp类型 + fileHead.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + colorTablesize + line_byte * height; //bfSize是图像文件4个组成部分之和,图文件的大小,以字节为单位 + fileHead.bfReserved1 = 0;//位图文件保留字,必须为0 + fileHead.bfReserved2 = 0; + fileHead.bfOffBits = 54 + colorTablesize; //bfOffBits是图像文件前3个部分所需空间之和,位图数据的起始位置 + + //申请位图信息头结构变量,填写信息头信息 + BITMAPINFOHEADER head; + head.biBitCount = biBitCount;//每个像素所需的位数,必须是1(双色),(29-30字节)4(16色),8(256色)16(高彩色)或24(真彩色)之一 + head.biCompression = BI_RGB; //位图压缩类型,必须为BI_RGB否则图片打开会有错误 + head.biHeight = height;//位图的高度,以像素为单位 + head.biWidth = width; + //head.biSize = 40; + head.biSize = sizeof(BITMAPINFOHEADER);//本结构所占用字节数 + head.biSizeImage = line_byte * height;//位图的大小(其中包含了为了补齐行数是4的倍数而添加的空字节) + head.biPlanes = 1;//目标设备的级别,必须为1 + head.biXPelsPerMeter = 23622;//位图水平分辨率,每米像素数,分辨率设为600 + head.biYPelsPerMeter = 23622;//位图垂直分辨率,每米像素数 + head.biClrImportant = 0;//位图显示过程中重要的颜色数 + head.biClrUsed = 0;//位图实际使用的颜色表中的颜色数 + + std::ofstream fp(dst.c_str(), std::ios::binary | std::ios::out); + if (!fp.is_open()) { + return -1; + } + fp.write((char*)&fileHead, sizeof(BITMAPFILEHEADER)); //写文件头进文件 + //写位图信息头进内存 + 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; +} + + diff --git a/client/webrtc_capture/src/cvhelper.h b/client/webrtc_capture/src/cvhelper.h new file mode 100644 index 0000000..2f9d870 --- /dev/null +++ b/client/webrtc_capture/src/cvhelper.h @@ -0,0 +1,17 @@ +#ifndef CVHELPER_H +#define CVHELPER_H + +// 常见opencv 图像操作的一层wrap + +#include "opencv2/opencv.hpp" +#include +#include +#include + +void TransferRGB2YCrCb(cv::Mat &input, std::vector &chls); +void MergeYCrCb2RGB(cv::Mat &output, std::vector &chls); +cv::Mat clahe_deal(cv::Mat &src, double ClipLimit , int TilesGridSize ); +int Save1BitImage(const cv::Mat img, std::string dst); +int Mat2Binary(const cv::Mat img, int line_byte, char* data); + +#endif // CVHELPER_H