在利用OpenCV对图像进行处理时,通常会遇到一个情况,就是只需要对部分感兴趣区域进行处理。
因此,如何选取感兴趣区域(其实就是“抠图”)。
下面给出一个例子:
Mat img = imread(IMG_PATH);
Mat cat = imread(CAT_PATH);
if (img.empty()|| cat.empty())
cerr << "can not read image."<;
// 指定感兴趣区域,两种方法
Mat ROI = img(Rect(40,40,cat.cols,cat.rows));
Mat ROI2(img,Rect(40,40,cat.cols,cat.rows));
// 展示 roi 区域
imshow("roi",ROI);
cout<"将猫放到感兴趣区域,两种方法"<;
//cat.copyTo(ROI);
cat.copyTo(ROI,cat);
imshow("lotus with cat",img);
// 在图像中画出 矩形
rectangle(img,Rect(240,240,cat.cols,cat.rows),Scalar(0,0,255));
imshow("with rectangle box",img);
// 另一种方法
cout <"利用 Rect 保存方框,然后使用"<;
Rect r1 = Rect(100,0,200,200);
rectangle(img,r1,Scalar(255,0,0));
imshow("with rectangle box 2",img);
Mat img = imread(IMG_PATH);
Mat dst;
Mat roi = Mat::zeros(img.size(),CV_8U);
vector<vector > contour;
vector pts;
pts.push_back(Point(30,45));
pts.push_back(Point(100,15));
pts.push_back(Point(300,145));
pts.push_back(Point(330,240));
pts.push_back(Point(50,250));
contour.push_back(pts);
drawContours(roi,contour,0,Scalar::all(255),-1);
img.copyTo(dst,roi);
imshow("roi",roi);
imshow("img",img);
imshow("dst",dst);
Mat image = imread(IMG_PATH);
Mat dst = Mat::zeros(image.size(), image.type());
Mat mask = Mat::zeros(image.size(),CV_8U);
Point circleCenter(mask.cols / 2, mask.rows / 2);
int radius = min(mask.cols, mask.rows)/2;
// 画圆
circle(mask, circleCenter, radius, Scalar(255),-1);
image.copyTo(dst, mask);
imshow("mask",mask);
imshow("image",image);
imshow("dst",dst);
效果如下:
- 问题:我想要个椭圆区域呢?
答:将上面代码中画圆的那一句替换为:
ellipse(mask,circleCenter,Size(240,146),10,-180,180,Scalar(255),-1);
效果如下:
- 问题:说了这么多,有什么规律么?
答:有啊。
其实主要用到了一个函数:copyTo,先看手册中 它的定义:
给出一个例子:
src.copyTo(dst, mask);
这里解释一下:将 src 的位于 mask 中的部分,拷贝到 dst 中。
这里,mask是一个“掩膜”, 其中非零的位置既是指定了 src 中的那些需要拷贝的部分。
上面才是整个方法的核心部分。
放大招:整体代码如下:
// csdn_code.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
#include
using namespace cv;
using namespace std;
//#define IMG_PATH "..//figures//12.jpg"
#define IMG_PATH "..//figures//lotus.jpg"
#define CAT_PATH "..//figures//cat.jpg"
void testroi(void){
Mat img = imread(IMG_PATH);
Mat cat = imread(CAT_PATH);
if (img.empty()|| cat.empty())
cerr << "can not read image."<// 指定感兴趣区域,两种方法
Mat ROI = img(Rect(40,40,cat.cols,cat.rows));
Mat ROI2(img,Rect(40,40,cat.cols,cat.rows));
// 展示 roi 区域
imshow("roi",ROI);
cout<"将猫放到感兴趣区域,两种方法"<//cat.copyTo(ROI);
cat.copyTo(ROI,cat);
imshow("lotus with cat",img);
// 在图像中画出 矩形
rectangle(img,Rect(240,240,cat.cols,cat.rows),Scalar(0,0,255));
imshow("with rectangle box",img);
// 另一种方法
cout <"利用 Rect 保存方框,然后使用"<100,0,200,200);
rectangle(img,r1,Scalar(255,0,0));
imshow("with rectangle box 2",img);
}
void contour_roi(void){
Mat img = imread(IMG_PATH);
Mat dst;
Mat roi = Mat::zeros(img.size(),CV_8U);
// 利用 边界设置roi区域
vector<vector > contour;
vector pts;
pts.push_back(Point(30,45));
pts.push_back(Point(100,15));
pts.push_back(Point(300,145));
pts.push_back(Point(330,240));
pts.push_back(Point(50,250));
contour.push_back(pts);
// 画出
drawContours(roi,contour,0,Scalar::all(255),-1);
img.copyTo(dst,roi);
imshow("roi",roi);
imshow("img",img);
imshow("dst",dst);
}
void circle_roi(void){
Mat image = imread(IMG_PATH);
Mat dst = Mat::zeros(image.size(), image.type());
Mat mask = Mat::zeros(image.size(),CV_8U);
Point circleCenter(mask.cols / 2, mask.rows / 2);
int radius = min(mask.cols, mask.rows)/2;
// 画圆
//circle(mask, circleCenter, radius, Scalar(255),-1);
// 画椭圆
ellipse(mask,circleCenter,Size(240,146),10,-180,180,Scalar(255),-1);
image.copyTo(dst, mask);
imshow("mask",mask);
imshow("image",image);
imshow("dst",dst);
}
int main()
{
testroi();
contour_roi();
circle_roi();
waitKey();
system("pause");
return 0;
}