cv::Mat转std::string
通过vector进行中转。但memcpy效率还是挺高的.
1 2 3 4 5 6 7 8 9 10 11
| cv::Mat mat = cv::imread("a.jpg"); std::vector<unsigned char> buff; cv::imencode(".jpg", mat, buff);
std::string str; str.resize(buff.size()); memcpy(&str[0], buff.data(), buff.size());
std::string str; str.assign(buff.begin(), buff.end());
|
std::string转cv::Mat
把std::string当做1行N列的数据,通过引用数据指针的方式来得到mat2。此时没有发生内存拷贝。
1 2 3 4 5 6 7
| cv::Mat mat(1, str.size(), CV_8U, (char *)str.data()); cv::Mat dst = cv::imdecode(mat, cv::IMREAD_UNCHANGED);
std::vector<uchar> view_buf(str.begin(), str.end()); cv::Mat view_image = cv::imdecode(view_buf, cv::ImreadModes::IMREAD_COLOR); view_buf.clear();
|
cv::Mat按行合并
1 2 3 4 5 6 7 8 9 10 11
| cv::Mat mergeRows(cv::Mat A, cv::Mat B) { int totalRows = A.rows + B.rows; cv::Mat mergedDescriptors(totalRows, A.cols, A.type()); cv::Mat submat = mergedDescriptors.rowRange(0, A.rows); A.copyTo(submat); submat = mergedDescriptors.rowRange(A.rows, totalRows); B.copyTo(submat); return mergedDescriptors; }
|
cv::Mat按列合并
1 2 3 4 5 6 7 8 9 10 11
| cv::Mat mergeCols(cv::Mat A, cv::Mat B) { int totalCols = A.cols + B.cols; cv::Mat mergedDescriptors(A.rows, totalCols, A.type()); cv::Mat submat = mergedDescriptors.colRange(0, A.cols); A.copyTo(submat); submat = mergedDescriptors.colRange(A.cols, totalCols); B.copyTo(submat); return mergedDescriptors; }
|
cv::Mat元素访问方式
这里介绍三种方式:
- 数组访问方式
- cv::Vec3b指针访问方式
- 字节指针访问方式
其中字节指针方式耗时最少,最高效,数组访问方式耗时最多,比较低效。其具体使用方式如下。
数组访问方式
1 2 3 4 5 6 7 8 9 10 11
| int w = image.cols; int h = image.rows; for (int row = 0; row < h; row++) { for (int col = 0; col < w; col++) { Vec3b bgr = image.at<Vec3b>(row, col); bgr[0] = 255 - bgr[0]; bgr[1] = 255 - bgr[1]; bgr[2] = 255 - bgr[2]; image.at<Vec3b>(row, col) = bgr; } }
|
cv::Vec3b指针访问方式
1 2 3 4 5 6 7 8 9 10 11
| int w = image.cols; int h = image.rows; for (int row = 0; row < h; row++) { Vec3b* curr = image.ptr<Vec3b>(row); for (int col = 0; col < w; col++) { Vec3b bgr = curr[col]; bgr[0] = 255 - bgr[0]; bgr[1] = 255 - bgr[1]; bgr[2] = 255 - bgr[2]; } }
|
字节指针方式
1 2 3 4 5 6 7 8 9 10 11
| int w = image.cols; int h = image.rows; for (int row = 0; row < h; row++) { uchar* uc_pixel = image.data + row * image.step; for (int col = 0; col < w; col++) { uc_pixel[0] = 255 - uc_pixel[0]; uc_pixel[1] = 255 - uc_pixel[1]; uc_pixel[2] = 255 - uc_pixel[2]; uc_pixel += 3; } }
|
图像resize
1 2 3 4 5
| double threshold = std::min(rx, ry); double ratio_x = rx / threshold; double ratio_y = ry / threshold; cv::Mat resize_image; cv::resize(src, resize_image, cv::Size(), ratio_x, ratio_y);
|
文件二进制转cv::Mat
有时会从文件读取图像文件的所有数据,或者来自网络的带格式的图像数据,转成cv::Mat如下:
1 2 3 4 5
| cv::Mat binary2Mat(std::string &&image) { cv::Mat m(1, image.size(), CV_8U, std::move(image.data())); cv::Mat img = cv::imdecode(m, cv::IMREAD_UNCHANGED); return std::move(img); }
|
深度图,伪rgb显示
- 单通道cv_32F测试可用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| cv::Mat depth2rgb(const std::string &vfilepath) { cv::Mat img = cv::imread(vfilepath, cv::IMREAD_UNCHANGED); cv::Mat img8U; cv::convertScaleAbs(img, img8U, 10); cv::mat rgb; cv::applyColorMap(img8U, rgb, cv::COLORMAP_JET); return std::move(rgb); }
int main(int argc, char *argv[]) { cv::Mat img = depth2rgb("test.tiff"); cv::imshow("tiff", img); cv::WaitKey(0); return 0; }
|
- 有时候数据以16位存储CV_16S1,根据实际情况转float,再映射到CV_8UC1,在渲染下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| cv::Mat comm::depth16U2Mat(std::string &raw) { float resolution_z = 0.0004f; float offset_z = 0.25f; cv::Mat data(1, raw.size(), CV_16UC1, std::move(raw.data())); cv::Mat img_16u = cv::imdecode(data, cv::IMREAD_ANYDEPTH); cv::Mat img_32f(img_16u.size(), CV_32FC1); cv::Mat img_8u(img_16u.size(), CV_8UC1); for (int r = 0; r < img_16u.rows; r++) { auto src_ptr = img_16u.ptr<short>(r); auto dst_ptr = img_32f.ptr<float>(r); for (int c = 0; c < img_16u.cols; c++) { dst_ptr[c] = offset_z + resolution_z * src_ptr[c]; } }
double min = -2, max = 2; double ratio = 255.0 / (max - min); double shift = -min * ratio; img_32f.convertTo(img_8u, CV_8U, ratio, shift); cv::Mat color_map; cv::applyColorMap(img_8u, color_map, cv::COLORMAP_BONE); return color_map; }
|
超范围裁图
如果裁图范围超过图像区域,超出的范围以0填充,rect的x, y可以是负数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| cv::Mat cropImage(const cv::Mat &src, const cv::Rect &rect) { cv::Mat dst = cv::Mat::zeros(rect.height, rect.width, 0); int crop_x1 = cv::Max(0, rect.x); int crop_y1 = cv::Max(0, rect.y); int crop_x2 = cv::min(src.cols - 1, rect.x + rect.width - 1); int crop_y2 = cv::min(src.rows - 1, rect.y + rect.height - 1); cv::Mat = roi_img = src(cv::Range(crop_y1, crop_y2 + 1), cv::Range(crop_x1, crop_x2 + 1));
int x1 = crop_x1 - rect.x; int y1 = crop_y1 - rect.y; int x2 = crop_x2 - rect.x; int y2 = crop_y2 - rect.y;
dst(cv::Range(y1, y2 + 1), cv::Range(x1, x2 + 1)) = dst(cv::Range(y1, y2 + 1), cv::Range(x1, x2 + 1)) + roi_img; return std::move(dst); }
|