行远-自迩

导航

Opencv ROI<8>

一、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>
         #define WINDOW_MAIN "LOGO"
         #define WINDOW_NEW "ROI"
 using namespace cv;
using namespace std;
Mat srcLogo, ROIRegion,SelectLogo;
Rect g_rectangle;
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);
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;
  }
 }
}
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);
}

三、掩码(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);
 
 }

posted on 2019-10-07 23:08  行远-自迩  阅读(252)  评论(0编辑  收藏  举报