learn opencv-如何在OpenCV中选择边界框(ROI)?

参考:https://github.com/spmallick/learnopencv


如何在OpenCV(C ++ / Python)中选择边界框(ROI)?

这里写图片描述

在本教程中,我们将学习如何在OpenCV中的图像中选择边界框或感兴趣区域(ROI)。 在过去,我们必须通过处理鼠标事件来编写我们自己的边界框选择器。 但是,现在我们可以选择使用OpenCV原生部分的函数selectROI。

我对OpenCV库中的奇怪选择感到惊讶。 您可能会认为selectROI将成为具有显示图像,绘图等功能的highgui的一部分。但是,selectROI是跟踪API的一部分! 正如你在后面会注意到的,写selectROI时所做的选择有点奇怪。 但是,在我们批评之前,我们得感谢有人制造出一些有用的东西,尽管它并不完美。

让我们深入看看selectROI的用法

如何在OpenCV中选择一个感兴趣的区域

由于selectROI是跟踪API的一部分,因此您需要使用opencv_contrib安装OpenCV 3.0(或更高版本)。

我们从一个示例代码开始。 它允许您在图像中选择一个矩形,裁剪矩形区域并最终显示裁剪后的图像。

我们将修改突出显示的行以尝试不同的选项。

C++

#include <opencv2/opencv.hpp>
// selectROI is part of tracking API
#include <opencv2/tracking.hpp>

using namespace std;
using namespace cv;


int main (int argc, char **arv)
{
    // Read image
    Mat im = imread("image.jpg");

    // Select ROI
    Rect2d r = selectROI(im);

    // Crop image
    Mat imCrop = im(r);

    // Display Cropped Image
    imshow("Image", imCrop);
    waitKey(0);

    return 0;
}

Python

import cv2
import numpy as np

if __name__ == '__main__' :

    # Read image
    im = cv2.imread("image.jpg")

    # Select ROI
    r = cv2.selectROI(im)

    # Crop image
    imCrop = im[int(r[1]):int(r[1]+r[3]), int(r[0]):int(r[0]+r[2])]

    # Display cropped image
    cv2.imshow("Image", imCrop)
    cv2.waitKey(0)

从左上角拖动矩形到右下角

如果你像我一样,你会喜欢把一个矩形从左上角拖到右下角,而不是从中心拖动。 那么,我们可以很容易地解决这个问题,用下面一行代替突出显示的行。

C++

bool fromCenter = false; 
Rect2d r = selectROI(im, fromCenter);

Python

fromCenter = False
r = cv2.selectROI(im, fromCenter)

如何指定窗口名称?

如果你可以使用现有的窗口而不是ROI选择器的窗口,这不是很好吗? 那么你走了

C++

bool fromCenter = false; 
Rect2d r = selectROI("Image", im, fromCenter);

Python

fromCenter = False
r = cv2.selectROI("Image", im, fromCenter)

不想显示十字线?

现在,假设你不喜欢十字准线,并希望看到没有它的矩形。 您可以修改代码以不显示十字线。

C++

bool showCrosshair = false; 
bool fromCenter = false; 
Rect2d r = selectROI("Image", im, fromCenter, showCrosshair);

Python

showCrosshair = False
fromCenter = False
r = cv2.selectROI("Image", im, fromCenter, showCrosshair)

如何在一个图像上选择多个感兴趣区域(roi)?

selectROI函数还允许您选择多个感兴趣的区域,但似乎有两个错误。

Bug警告1:根据说明,您可以拖动一个矩形,然后按ENTER并拖动另一个矩形。 但是,OpenCV 3.2中的实现似乎存在一个错误。 您必须在第一个矩形后两次按ENTER键。 对于所有后续的矩形,您应该按ENTER一次。

C++

// Specify a vector of rectangles (ROI) 
vector<Rect2d> rects;
bool fromCenter = false; 
// The selected rectangles are in
selectROI("Image", im, rects, fromCenter);

错误警报2:我不能让python版本工作,没有文档。 下面的代码运行,但是变量rects没有被填充。 该函数也不会返回任何东西。 如果您发现修复,请在下面的评论中告诉我。

Python

# Note this code does not work. 
# Specify a vector of rectangles (ROI) 
rects = []
fromCenter = false
# Select multiple rectangles
selectROI("Image", im, rects, fromCenter)
### 使用Python和OpenCV实现汉字识别 为了实现汉字识别,可以采用一种结合图像处理技术和光学字符识别(OCR)技术的方式。此方法依赖于两个主要组件:一是用于预处理图片并定位文字区域的工具;二是能够解析这些区域内字符的具体内容的OCR引擎。 对于前者,OpenCV是一个强大的开源计算机视觉库,提供了丰富的函数来进行图像变换、特征提取以及模式匹配等工作[^1]。后者则通常会选择Tesseract OCR这样的专用软件包,它支持多种语言的文字识别,包括中文在内的多国语言。 #### 安装所需环境与库 在开始之前,确保已经安装了必要的Python库: ```bash pip install opencv-python tesseract pytesseract numpy matplotlib scikit-learn easyocr ``` 其中`pytesseract`是调用Tesseract命令行接口的一个封装库,而`easyocr`则是另一个高效的OCR解决方案,在处理亚洲语言方面表现尤为出色[^5]。 #### 图像预处理阶段 利用OpenCV读取待分析的照片,并对其进行一系列增强操作以便后续更精准地捕捉到目标对象上的文字信息。这可能涉及到灰度化、二值化、去噪等步骤。 ```python import cv2 import numpy as np def preprocess_image(image_path): img = cv2.imread(image_path, 0) # 加载为灰度图 _, thresh_img = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) kernel = np.ones((3, 3), np.uint8) opening = cv2.morphologyEx(thresh_img, cv2.MORPH_OPEN, kernel, iterations=2) sure_bg = cv2.dilate(opening, kernel, iterations=3) dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5) _, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0) sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(sure_bg, sure_fg) contours, _ = cv2.findContours(sure_fg.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2:] return contours ``` 这段代码实现了从原始输入图像中分离出前景(即可能是文本的部分),并通过形态学运算去除噪声干扰项,最终返回疑似含有文字轮廓的对象列表。 #### 文字位置检测及分割 一旦获得了潜在包含文字的目标区域,则可以通过边界框来限定它们的确切范围,并进一步切割成单个字符供下一步骤使用。 ```python def detect_and_split_characters(contours, image): char_images = [] for cnt in sorted(contours, key=lambda c: cv2.boundingRect(c)[0]): x, y, w, h = cv2.boundingRect(cnt) if all([w > 10, h > 10]): # 过滤掉过小的矩形 roi = image[y:y+h, x:x+w] resized_roi = cv2.resize(roi, (64, 64)) # 统一尺寸方便后期处理 char_images.append(resized_roi) return char_images ``` 这里定义了一个辅助函数用来接收由前一步得到的所有候选区间的集合,并按照水平坐标顺序排列后逐一裁剪保存下来形成新的子图像序列。 #### 应用OCR进行字符识别 最后就是将上述准备好的每一张单独的小图送入选定的OCR服务当中完成最终的任务——识别人物姓名或其他形式的汉字符号串。 ```python from PIL import Image import pytesseract from easyocr import Reader reader = Reader(['ch_sim']) # 初始化EasyOCR模型实例 for idx, char_img in enumerate(char_images): pil_im = Image.fromarray(cv2.cvtColor(char_img,cv2.COLOR_BGR2RGB)) result_tess = pytesseract.image_to_string(pil_im, lang='chi_sim') print(f"Tesseract Result {idx}: ", result_tess.strip()) result_easy = reader.readtext(np.array(pil_im))[0][1] if len(reader.readtext(np.array(pil_im)))>0 else '' print(f"EasyOCR Result {idx}: ", result_easy) ``` 以上展示了两种不同的方式来做汉字识别测试,分别采用了Tesseract和EasyOCR这两个不同特性的OCR工具。可以根据实际情况对比两者的性能差异选择更适合项目需求的一种方案。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值