您的位置:首页 > 其它

图像处理之ROI区域裁剪

2017-06-15 17:26 204 查看
图像ROI(region of intrest:感兴趣区域)的提取往往是图像处理中的第一步,而且也是非常关键的一步,ROI区域的提取能够在消除一些噪

声的同时减少后续图像处理的数据量,是非常常用的方法。

在OPENCV中可以利用数据结构Rect 来提取ROI区域,具体用法示例如下:

int main()
{
Mat image = imread("sources/1.bmp", 0);
Rect ROI(10, 20, 300, 400);
Mat img = image(ROI);
imwrite("result/ROI.bmp", img);
int aaa;
cin >> aaa;
return 0;
}


在这段程序中,原图是image,裁剪区域是以坐标(300,500)为左上角,宽为300,高为400的一个矩形区域,如下图:

原图:1.bmp



裁剪结果如下:RIO.bmp



那么现在就存在一个问题,对于大多数的图像处理项目来说,每幅图像的ROI并不一定是在固定的区域,甚至ROI区域的大小也可能是不一样的,
也就是说在具体裁剪的时候裁剪的位置及矩形区域都是要根据每幅图像来具体确定的,这里将举一个例子进行说明:如下图是一幅啤酒盖的图像,
在后续的检测或者分类中我们只关心啤酒盖所在的区域,也就是说我们ROI区域是包含且仅包含整个啤酒盖的一个矩形区域,如何提取呢?



我的做法,首先对原图进行二值化,然后提取整个图像区域内最大的连通区域,如下图:



在得到这个最大的连通区域,其实也就是啤酒盖所在的区域,我是通过遍历整个图像,找到0度,90度,180度及270度,
四个方向上连通域最靠近图像边缘的点,然后通过这四个点就能用一个矩形框将整个连通区域框出来,代码如下,
采用的是几种遍历方法中最高效的方法:

int up = image.rows, left = image.cols, right = 0, down = 0;
int flag = 0;
int nr = image.rows, nc = image.cols;
if (image.isContinuous())
{
nr = 1;
nc = nc*image.rows;//convert 2D to 1D if the image is continuous
flag = 1;
}
//cout << "flag=" << flag << endl;
if (flag == 1)//situation 1:the image is continuous
{
for (int i = 0; i < nr; i++)
{
const uchar* inData = region.ptr<uchar>(i);
for (int j = 0; j < nc; j++)
{
if (*inData == 0 && *(inData + 1) == 255)
{
int row = (j + 1) / (region.cols);
int col = (j + 1) - row*region.cols;
if (row < up)
{
up = row;
}
if (col < left)
{
left = col;
}
}
if (*inData == 255 && *(inData + 1) == 0)
{
int row = j / (region.cols);
int col = j - row*region.cols;
if (row > down)
{
down = row;
}
if (col > right)
{
right = col;
}
}
inData++;
}
}
}
else//situation 2:the image is not continuous
{
for (int i = 0; i < nr; i++)
{
const uchar* inData = region.ptr<uchar>(i);
for (int j = 0; j < nc; j++)
{
if (*inData == 0 && *(inData + 1) == 255)
{
int row = i;
int col = j;
if (row < up)
{
up = row;
}
if (col < left)
{
left = col;
}
}
if (*inData == 255 && *(inData + 1) == 0)
{
int row = i;
int col = j;
if (row > down)
{
down = row;
}
if (col > right)
{
right = col;
}
}
inData++;
}
}
}
bb[0] = Point2i(left, up);
bb[1] = Point2i(right, down);
}
其中bb[0],bb[1]是两个坐标点,分别是确定要裁剪的矩形框的左上角与右下角在原图中的坐标,
根据这两个坐标点,可以利用Rect数据类型对原图进行裁剪,如下:
Rect roi(bb[0].x,bb[0].y,bb[1].x-bb[0].x,bb[1].y-bb[0].y)
最终的裁剪结果如下:



显然通过以上办法,实现了对于感兴趣区域的裁剪。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: