一、ROI 介绍
1. ROI (Region of Interest) 感兴趣区域,就是从图像中选择一个图像区域,这个区域就是图像分析所关注的焦点。圈定这个区域,那么要处理的图像就从大图像变为一个小图像区域了,这样以便进行进一步处理,可以大大减小处理时间。
2. 定义ROI方法:
- 使用表示矩阵区域的Rect。
它指定矩阵的左上角坐标(构造函数的前两个参数)和矩阵的长宽(构造函数的后两个参数)以定义一个矩阵区域。
Mat imageROI;
imageROI = image(Rect(200,200,500,500);//Rect四个形参分别是:x坐标,y坐标,长,高;注意(x,y)指的是矩形的左上角
- 指定感兴趣行或列的范围(Range)。
Range是指从起索引到终止索引(不包括终止索引)的一连串连续序列。cRange可以用来定义Range。如果使用Range来定义ROI,那么前例中定义ROI 的代码可以重写为:
imageROI = image( Range(250, 250+logoImage.rows), Range(200, 200+logoImage.cols));//Range两个形参分别是:起始行或列,起始行或列+偏移量
二、鼠标事件标注ROI区域并选择出来
直接上程序,下面的程序,经历了一下午,跳进了大坑,始终没有发现,直至现在,感觉很搞笑有时很想往自己脸上打几下,看来代码还是的多写,学会调适。
#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
#define WINDOW_MAIN "LOGO"
#define WINDOW_NEW "ROI"
#define WINDOW_NEW "ROI"
using namespace cv;
using namespace std;
using namespace std;
Mat srcLogo, ROIRegion,SelectLogo;
Rect g_rectangle;
bool g_bDrawingBox = false;
bool g_bDrawFinished = false;
bool g_bDrawingBox = false;
bool g_bDrawFinished = false;
void on_MouseHandle(int event, int x, int y, int flags, void* param);
void DrawRectangle(Mat& img, Rect box);
void DrawRectangle(Mat& img, Rect box);
Mat srcImage(600, 800, CV_8UC3), Temp;
void main()
{
srcLogo = imread("E:\欣奕华\项目\OPENCV\ROI\2.jpg", 1);
if (srcLogo.data == NULL)
{
cout << "srcLogo 读取失败" << endl;
}
srcLogo.copyTo(Temp);
//g_rectangle = Rect(-1, -1, 0, 0);
//srcImage = Scalar::all(0);
namedWindow(WINDOW_MAIN,1);
setMouseCallback(WINDOW_MAIN, on_MouseHandle, &SelectLogo);
while (1)
{
srcLogo.copyTo(SelectLogo);
imshow(WINDOW_MAIN, SelectLogo);
if (g_bDrawFinished == true)
{
DrawRectangle(SelectLogo, g_rectangle);
ROIRegion = SelectLogo(Rect(g_rectangle.x, g_rectangle.y, g_rectangle.width, g_rectangle.height));
imshow(WINDOW_NEW, ROIRegion);
}
//下面的这句话真是他妈的该死!!!!!
int key = waitKey();
while ((char)key == 'Q' || (char)key == 'q')
{
return;
}
}
}
int key = waitKey();
while ((char)key == 'Q' || (char)key == 'q')
{
return;
}
}
}
void on_MouseHandle(int event, int x, int y, int flags, void* param)
{
Mat& image = *(Mat*)param;
image = Scalar::all(0);
switch (event)
{
case EVENT_LBUTTONDOWN:
{
g_bDrawingBox = true;
g_bDrawFinished = false;
g_rectangle = Rect(x, y, 0, 0);
break;
}
case EVENT_MOUSEMOVE:
{
if (g_bDrawingBox == true)
{
g_rectangle.width = x - g_rectangle.x;
g_rectangle.height = y - g_rectangle.y;
}
break;
}
case EVENT_LBUTTONUP:
{
g_bDrawingBox = false;
g_bDrawFinished = true;
if (g_rectangle.width < 0)
{
g_rectangle.x += g_rectangle.width;
g_rectangle.width *= -1;
}
if (g_rectangle.height < 0)
{
g_rectangle.y += g_rectangle.height;
g_rectangle.height *= -1;
}
DrawRectangle(image, g_rectangle);
break;
}
default:
break;
}
}
void DrawRectangle(Mat& img, Rect box)
{
rectangle(img, box.tl(), box.br(), Scalar(255, 200, 55), 2);
}
{
Mat& image = *(Mat*)param;
image = Scalar::all(0);
switch (event)
{
case EVENT_LBUTTONDOWN:
{
g_bDrawingBox = true;
g_bDrawFinished = false;
g_rectangle = Rect(x, y, 0, 0);
break;
}
case EVENT_MOUSEMOVE:
{
if (g_bDrawingBox == true)
{
g_rectangle.width = x - g_rectangle.x;
g_rectangle.height = y - g_rectangle.y;
}
break;
}
case EVENT_LBUTTONUP:
{
g_bDrawingBox = false;
g_bDrawFinished = true;
if (g_rectangle.width < 0)
{
g_rectangle.x += g_rectangle.width;
g_rectangle.width *= -1;
}
if (g_rectangle.height < 0)
{
g_rectangle.y += g_rectangle.height;
g_rectangle.height *= -1;
}
DrawRectangle(image, g_rectangle);
break;
}
default:
break;
}
}
void DrawRectangle(Mat& img, Rect box)
{
rectangle(img, box.tl(), box.br(), Scalar(255, 200, 55), 2);
}
三、掩码(mask)
四、不规则ROI提取
原理:先滤波-->>灰度化-->>二值化-->>边缘提取-->>寻找图像轮廓-->>轮廓画在一张空图像-->>水漫填充图像轮廓区域-->>两个图像与操作
#include<iostream>
#include <opencv2/opencv.hpp>
#include <math.h>
using namespace cv;
using namespace std;
#define WINDOWS_INPUT "输入原图"
#define WINDOWS_BLUR "滤波图"
#define WINDOWS_GRAY "灰度图"
#define WINDOWS_THRESHOLD "二值化图"
#define WINDOWS_CONTOURS "轮廓图"
RNG rng = theRNG();
Mat inputImage, outputImage, thresholdImage,blurImage,grayImage;
int thredholdValue = 50;
const int Threshold_Max_value = 255;
const int Threshold_type_value = 3;
double g_Area = 0;
int MaxareaCount = 0;void Threshold_Image_Bar(int, void *);
void main()
{
inputImage = imread("E:\欣奕华\项目\OPENCV\ROI\NonRegionRIO\1.jpg", 1);
if (inputImage.data == NULL)
{
cout << "inputImage 读取错误" << endl;
}
namedWindow(WINDOWS_INPUT, 1);
imshow(WINDOWS_INPUT, inputImage);//1. 滤波
blur(inputImage, blurImage, Size(3, 3), Point(-1, -1),4);
namedWindow(WINDOWS_BLUR, 1);
imshow(WINDOWS_BLUR, blurImage);//2. 灰度图
cvtColor(blurImage, grayImage, COLOR_BGR2GRAY);
namedWindow(WINDOWS_GRAY, 1);
imshow(WINDOWS_GRAY, grayImage);//3.二值化
namedWindow(WINDOWS_THRESHOLD, 1);
createTrackbar("阈值调整", WINDOWS_THRESHOLD, &thredholdValue, Threshold_Max_value, Threshold_Image_Bar);
Threshold_Image_Bar(0, 0);
//namedWindow(WINDOWS_THRESHOLD, 1);
// imshow(WINDOWS_THRESHOLD, thresholdImage);
waitKey(0);
}void Threshold_Image_Bar(int, void *)
{
//二值化处理,支持就地处理
threshold(grayImage, thresholdImage, 90, 255,THRESH_TOZERO);
//边缘检测,支持就地处理
Canny(thresholdImage, thresholdImage, thredholdValue, thredholdValue * 3, Threshold_type_value);
namedWindow(WINDOWS_THRESHOLD, 1);
imshow(WINDOWS_THRESHOLD, thresholdImage);//寻找,绘制轮廓
vector<vector<Point>> contours;
vector<Vec4i> hireachy;
findContours(thresholdImage, contours, hireachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(-1, -1));
Mat Show_threImage = Mat::zeros(thresholdImage.size(), CV_8UC3);
RotatedRect rotateRect;
for (int i = 0; i < contours.size(); i++)
{
Scalar Color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(Show_threImage, contours, i, Color, 1, 8, hireachy, 0, Point());
//利用面积寻找最大区域
double area = contourArea(contours[i]);
g_Area = g_Area > area ? g_Area : area;
MaxareaCount = (g_Area == area) ? i : MaxareaCount;
}
namedWindow(WINDOWS_CONTOURS, 1);
imshow(WINDOWS_CONTOURS, Show_threImage);//空白图像画轮廓:
Mat gray, Change_image = Mat::zeros(inputImage.size(), inputImage.type());
gray.create(inputImage.size(), inputImage.type());
drawContours(gray, contours, MaxareaCount, Scalar(255, 255, 255), 2, 8, hireachy, 0, Point());
Rect s = boundingRect(contours[MaxareaCount]);//为了找内部的一个种子点,自己随便定义也可以
//水漫之后的图像:
floodFill(gray, Point(s.x + s.width / 2, s.y + s.height / 2), Scalar(255, 255, 255));//黑色区域变成白色,遇到白色区域停止
imshow("123", gray);
bitwise_and(inputImage, gray, gray);
// imshow("wjy", gray);
}