由于我们一般画矩形都是通过整个图像进行遍历,如果我们选取的ROI区域很大,这样的做法时间复杂度和空间复杂度很大。基于此考虑在大的ROI区域在四个顶点选取四个小的矩形区域从而来确定大的ROI区域:
测试文件:test.cpp
#include<opencv2/opencv.hpp>
#include<iostream>
#include<fstream>
#include<quickopencv.h>
using namespace cv;
using namespace std;
Mat roi_select(Mat& image, Point sp, Point ep) {
int dx = ep.x - sp.x;
int dy = ep.y - sp.y;
Rect box(sp.x, sp.y, dx, dy);//ROI区域大小
Mat new_img = image(box);
/*QuickDemo qd;
Mat ROI_his = qd.histogram_grayImage(new_img);
namedWindow("ROI_his", WINDOW_FREERATIO);
imshow("ROI_his", ROI_his);*/
return new_img;
}
int main()
{
Mat src = imread("C:\\Users\\Administrator\\Documents\\WXWork\\1688850162194623\\Cache\\File\\2021-08\\0015.bmp");
if (src.empty())
{
printf("could not load image...");
return -1;
}
namedWindow("input_image", WINDOW_FREERATIO);
imshow("input_image", src);
int height = src.rows;
int width = src.cols;
cv::Mat textureMat(height, width, CV_8UC3);
std::ifstream("C:\\Users\\Administrator\\Documents\\WXWork\\1688850162194623\\Cache\\File\\2021 - 08\\0015.bmp",
std::ios::in | std::ios::binary).read((char*)textureMat.data,width * height * 3 * sizeof(uchar));
cv::Mat heightMat(height, width, CV_32FC1);
std::ifstream("C:\\Users\\Administrator\\Documents\\WXWork\\1688850162194623\\Cache\\File\\2021-08\\0015_13",
std::ios::in | std::ios::binary).read((char*)heightMat.data, width * height * sizeof(float));
QuickDemo qd;
Mat hist = qd.histogram_grayImage(heightMat);
namedWindow("hist", WINDOW_FREERATIO);
imshow("hist", hist);
//left_top
Mat new_heightMat_lefttop = roi_select(heightMat, Point(666, 1706), Point(785, 1777));
Mat new_src_lefttop = roi_select(src, Point(666, 1706), Point(785, 1777));
//left_bottom
Mat new_heightMat_leftbot = roi_select(heightMat, Point(666, 2926), Point(785, 2997));
Mat new_src_leftbot = roi_select(src, Point(666, 2926), Point(785, 2997));
//right_bottom
Mat new_heightMat_rightbot = roi_select(heightMat, Point(1911, 2926), Point(2030, 2997));
Mat new_src_rightbot = roi_select(src, Point(1911, 2926), Point(2030, 2997));
//right_top
Mat new_heightMat_righttop = roi_select(heightMat, Point(1911, 1706), Point(2030, 1777));
Mat new_src_righttop = roi_select(src, Point(1911, 1706), Point(2030, 1777));
//掩模
qd.image_mask(new_src_lefttop, new_heightMat_lefttop);
qd.image_mask(new_src_leftbot, new_heightMat_leftbot);
qd.image_mask(new_src_righttop, new_heightMat_righttop);
qd.image_mask(new_src_rightbot, new_heightMat_rightbot);
qd.image_mask(new_src_rightbot, new_heightMat_rightbot);
namedWindow("形态学操作前", WINDOW_FREERATIO);
imshow("形态学操作前", src);
qd.elementsizechange_close_demo(src);
qd.draw_interset(src);
waitKey(0);
return 0;
}
cpp的函数:
void QuickDemo::image_mask(Mat& image, Mat& heightMat)
{
Mat dst;
cvtColor(image, dst, COLOR_BGR2GRAY);
int h_height = heightMat.rows;
int h_width = heightMat.cols;
//mask
for (int row = 0; row < h_height; row++)
{
for (int col = 0; col < h_width; col++)
{
if (heightMat.at<float>(row, col) > 1000)//高度大于1000
{
image.at<Vec3b>(row, col)[0] = 0;
image.at<Vec3b>(row, col)[1] = 0;
image.at<Vec3b>(row, col)[2] = 255;
}
}
}
}
形态学操作:
void QuickDemo::elementsizechange_close_demo(Mat& image) {
//闭操作
Mat dst;
int elementsize = 4;
Mat kernel = getStructuringElement(MORPH_RECT, Size(elementsize * 2 + 1, elementsize * 2 + 1));
morphologyEx(image, dst, MORPH_CLOSE, kernel);
namedWindow("形态学操作以后", WINDOW_FREERATIO);
imshow("形态学操作以后", dst);
}
下面代码是:对于图片中的红色区域画一个最小矩形把红色区域包围。
void QuickDemo::draw_interset(Mat &image_add)
{
int h = image_add.rows; // 原图高
int w = image_add.cols; // 原图宽
vector<Point> points; // 设置容器,用来存储坐标
for (int row = 0; row < h; row++) {
for (int col = 0; col < w; col++) {
if (image_add.at<Vec3b>(row, col)[0] == 0 &&
image_add.at<Vec3b>(row, col)[1] == 0 &&
image_add.at<Vec3b>(row, col)[2] == 255) {
// 查找符合要求的像素点
Point midPoint;
midPoint.x = col;
midPoint.y = row;
points.push_back(midPoint);
}
}
}
Rect rect = boundingRect(points);
rectangle(image_add, rect, Scalar(0, 0, 255), 4, 8);
namedWindow("add_mask", WINDOW_FREERATIO);
imshow("add_mask", image_add);
}
原始图像
高度直方图
ROI的四个顶点区域
通过四个顶点画ROI区域