OpenCV—使用ROI进行图像切割

OpenCV—使用ROI进行图像切割

ROI(region of interest)——感兴趣区域。

1.用途

这个区域是图像分析所关注的重点。圈定这个区域,以便进行进一步的处理。而且,使用ROI指定

想读入的目标,可以减少处理时间,增加精度,给图像处理带来不小的便利。

2.定义ROI方法

  • 使用表示矩阵区域的Rect。

它指定矩阵的左上角坐标(构造函数的前两个参数)和矩阵的长宽(构造函数的后两个参数)以定义一个矩阵区域。

// 定义一个Mat类型并给定其设定的区域
Mat imageROI;
// 方法一
imageROI = image(Rect(500, 250, logo.cols, logo.rows));
  • 指定感兴趣行或列的范围(Range)。

Range是指从起索引到终止索引(不包括终止索引)的一连串连续序列。cRange可以用来定义Range。如果使用Range来定义ROI,那么前例中定义ROI的代码可以重写为:

// 方法二
imageROI = image( Range(250, 250+logoImage.rows), 
                                        Range(200, 200+logoImage.cols));

 3.切割具体步骤

  • 将要切割下的图像区域局部设置为ROI
void cvSetImageROI(IplImage* image,CvRect rect);
  • 创建一个与切割图像大小相同的新图像
IplImage* cvCreateImage( CvSize size, int depth, int channels );

    depth 图像元素的位深度,可以是下面的其中之一:

   

IPL_DEPTH_8U无符号8位整型
IPL_DEPTH_8S有符号8位整型
IPL_DEPTH_16U无符号16位整型
IPL_DEPTH_16S有符号16位整型
IPL_DEPTH_32F单精度浮点数
IPL_DEPTH_64F双精度浮点数
  

 

    channels 每个元素(像素)通道数.可以是 1, 2, 3 或 4.通道是交叉存取的

  • 将原图像复制到新图像中
void cvCopy( const CvArr* src, CvArr* dst, const CvArr* mask=NULL ); 

     操作掩码是8比特单通道的数组,它指定了输出数组中被改变的元素。函数cvCopy从输入数组中复制选定的成分到输出数组:

    如果mask(I)!=0,则dst(I)=src(I)。

    如果输入输出数组中的一个是IplImage类型的话,其ROI和COI将被使用。输入输出数组必须是同样的类型、维数和大小。函数也可以用来复制散列数组(这种情况下不支持mask)。

  • 释放ROI区域
cvResetIamgeROI(src);

4.实例
  如何利用ROI将一幅图加到另一幅图的指定位置。

  通过一个图像掩码,直接将插入处的像素设置为插入图像的像素值,这样效果会很逼真。

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

using namespace cv;
using namespace std;

bool  ROI_AddImage();
bool  LinearBlending();
bool  ROI_LinearBlending();
void   ShowHelpText();

int main(   )
{
    system("color 6F");

    if(ROI_AddImage( )&& LinearBlending( )&&ROI_LinearBlending( ))
    {
        cout<<endl<<"\n运行成功,得出了需要的图像";
    }

    waitKey(0);
    return 0;
}




//----------------------------------【ROI_AddImage( )函数】----------------------------------
// 函数名:ROI_AddImage()
//    描述:利用感兴趣区域ROI实现图像叠加
//----------------------------------------------------------------------------------------------
bool  ROI_AddImage()
{

    // 【1】读入图像
    Mat srcImage1= imread("dota_pa.jpg");
    Mat logoImage= imread("dota_logo.jpg");
    if( !srcImage1.data ) { printf("读取srcImage1错误~! \n"); return false; }
    if( !logoImage.data ) { printf("读取logoImage错误~! \n"); return false; }

    // 【2】定义一个Mat类型并给其设定ROI区域
    Mat imageROI= srcImage1(Rect(200,250,logoImage.cols,logoImage.rows));

    // 【3】加载掩模(必须是灰度图)
    Mat mask= imread("dota_logo.jpg",0);

    //【4】将掩膜拷贝到ROI
    logoImage.copyTo(imageROI,mask);

    // 【5】显示结果
    namedWindow("<1>利用ROI实现图像叠加示例窗口");
    imshow("<1>利用ROI实现图像叠加示例窗口",srcImage1);

    return true;
}


//---------------------------------【LinearBlending()函数】-------------------------------------
// 函数名:LinearBlending()
// 描述:利用cv::addWeighted()函数实现图像线性混合
//--------------------------------------------------------------------------------------------
bool  LinearBlending()
{
    //【0】定义一些局部变量
    double alphaValue = 0.5; 
    double betaValue;
    Mat srcImage2, srcImage3, dstImage;

    // 【1】读取图像 ( 两幅图片需为同样的类型和尺寸 )
    srcImage2 = imread("mogu.jpg");
    srcImage3 = imread("rain.jpg");

    if( !srcImage2.data ) { printf("读取srcImage2错误! \n"); return false; }
    if( !srcImage3.data ) { printf("读取srcImage3错误! \n"); return false; }

    // 【2】进行图像混合加权操作
    betaValue = ( 1.0 - alphaValue );
    addWeighted( srcImage2, alphaValue, srcImage3, betaValue, 0.0, dstImage);

    // 【3】显示原图窗口
    imshow( "<2>线性混合示例窗口【原图】", srcImage2 );
    imshow( "<3>线性混合示例窗口【效果图】", dstImage );

    return true;

}

//---------------------------------【ROI_LinearBlending()】-------------------------------------
// 函数名:ROI_LinearBlending()
// 描述:线性混合实现函数,指定区域线性图像混合.利用cv::addWeighted()函数结合定义
//              感兴趣区域ROI,实现自定义区域的线性混合
//--------------------------------------------------------------------------------------------
bool  ROI_LinearBlending()
{

    //【1】读取图像
    Mat srcImage4= imread("dota_pa.jpg",1);
    Mat logoImage= imread("dota_logo.jpg");

    if( !srcImage4.data ) { printf("读取srcImage4错误~! \n"); return false; }
    if( !logoImage.data ) { printf("读取logoImage错误~! \n"); return false; }

    //【2】定义一个Mat类型并给其设定ROI区域
    Mat imageROI;
    //方法一
    imageROI= srcImage4(Rect(200,250,logoImage.cols,logoImage.rows));
    //方法二
    //imageROI= srcImage4(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));

    //【3】将logo加到原图上
    addWeighted(imageROI,0.5,logoImage,0.3,0.,imageROI);

    //【4】显示结果
    imshow("<4>区域线性图像混合示例窗口",srcImage4);

    return true;
}

 

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用OpenCV进行答题卡识别,您可以按照以下步骤进行: 1. 导入所需的库: ``` import cv2 import numpy as np ``` 2. 加载答题卡图像: ``` image = cv2.imread('path_to_image', cv2.IMREAD_GRAYSCALE) ``` 3. 对图像进行预处理: - 应用高斯模糊以去除噪声: ``` blurred = cv2.GaussianBlur(image, (5, 5), 0) ``` - 进行二值化,将图像转换为黑白: ``` _, thresh = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) ``` 4. 检测轮廓: ``` contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) ``` 5. 对轮廓进行筛选和排序: - 筛选出符合预期形状和大小的轮廓: ``` min_area = 1000 # 最小轮廓面积 max_area = 50000 # 最大轮廓面积 selected_contours = [] for contour in contours: area = cv2.contourArea(contour) if min_area < area < max_area: selected_contours.append(contour) ``` - 根据轮廓的位置进行排序: ``` sorted_contours = sorted(selected_contours, key=lambda c: cv2.boundingRect(c)[0]) ``` 6. 识别答题卡选项: - 根据特定区域进行切割和识别: ``` for contour in sorted_contours: x, y, w, h = cv2.boundingRect(contour) roi = thresh[y:y+h, x:x+w] # 进行选项识别的代码... ``` - 可以使用OCR(光学字符识别)库,如Tesseract,对选项进行识别: ``` import pytesseract option_text = pytesseract.image_to_string(roi, config='--psm 10 --oem 3') ``` 通过以上步骤,您可以使用OpenCV进行答题卡识别,并根据需求进一步处理和分析识别的结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值