4.通道分离split()与合成merge()以及去除票据上的印章 --- OpenCV从零开始到图像(人脸 + 物体)识别系列

  • 完成时间:2018-5-14

  • 作者:小嗷

  • qq邮箱:631821577@qq.com

  • qq群:736857977

  • 公众号:小嗷的日常(扫码关注)

    0.二维码

老是学习API函数,确实没意思。但是,编程几乎所有的初学者都是这么来的。然而,尽量结合实际,却发现每个细节都有意思。


在图像处理时,我们接触到的彩色以RGB居多,为了分析图像在某一通道上的特性,需要将图像的颜色通道进行分离,或者是在对某一颜色通道处理后重新进行融合。opencv提供了split()函数来进行颜色通道的分离,提供了merge()函数来进行颜色通道的融合。


1.split()函数

此函数的作用是将一个图像通道进行分离。

split()函数定义:

void split(const Mat& m, vector<mat>& mv );</mat>

参数说明:

  • const Mat&类型的src,填我们需要进行分离的图像;
  • vector<mat style="margin-top: 0px;">类型的mv,填函数的输出数组或者输出的vector容器,即分离后的图像;</mat>

2.merge()函数

merge()函数的功能是split()函数的逆向操作,将多个数组合并成一个多通道的数组。

merge()函数定义:

void merge(const vector<mat>& mv, OutputArray dst );</mat>

  • const <mat style="margin-top: 0px;">类型的mv,填需要被合并的vector容器的阵列,这个mv参数中所有的矩阵必须有着一样的尺寸和深度;</mat>
  • 保存为合并后的图像;

3.利用split()函数和阈值化去除票据上的印章,merge()函数合并图像


票据上往往会有一些红色印章把一些重要信息区域给覆盖了,比如一些开发票人员盖印章时比较随意,容易吧一些关键区域给遮蔽了,这让接下来的票据识别很困难,因此,我们必须先对票据图像进行一定的预处理来移除印章干扰,再进行字符识别,这样子识别准确率才有保证。


  • 任务:我们需要识别发票的字体(红色盖章影响都我们的识别工作)

如图:

1.发票原图.jpg
  • 分析场景:这种发票只有章是红色,字体为黑色为主
  • 怎么去除该种发票红色部分?利用split()分离红色通道浅化目标,再利用阈值把浅化目标,过滤掉。(阈值用来过滤比较浅的颜色【其中一种用法】)
2.通道图.PNG
  • 第二张图为分离红色通道的图,明显比其他三张浅的(红色部分)
3.通道图阈值化.PNG
  • 最后一张过滤掉红章图

代码如下

4.代码.PNG
#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc/imgproc.hpp>  
#include <iostream>
using namespace cv;
using namespace std;

int main() {
    //【1】定义相关变量
    Mat srcImage, newImage;
    Mat srcImage_B, srcImage_G, srcImage_R;
    //【2】存放Mat的数组vector
    vector<Mat> channels_BGR;
    //【3】读取原始图像并检查图像是否读取成功    
    srcImage = imread("D:\\1.发票原图.jpg");
    if (srcImage.empty())
    {
        cout << "读取图像有误,请重新输入正确路径!\n";
        getchar();
        return -1;
    }
    imshow("src原图像",srcImage);  //在窗口显示原图像
    //【4】对加载的原图像进行通道分离,即把一个3通道图像转换成为3个单通道图像  
    split(srcImage,channels_BGR);
    //从数组中取出3种颜色,0通道为B分量,1通道为G分量,2通道为R分量。因为:RGB色彩空间在opencv中默认通道顺序为BGR!!!
    srcImage_B = channels_BGR.at(0);
    srcImage_G = channels_BGR.at(1);
    srcImage_R = channels_BGR.at(2);
    imshow("srcImage_B通道", srcImage_B); //分别显示R,G,B各个通道图像  
    imshow("srcImage_G通道", srcImage_G);
    imshow("srcImage_R通道", srcImage_R);

    //【5】 全局二值化
    Mat gray;
    cvtColor(srcImage,gray, CV_RGB2GRAY);
    int th = 170; //阈值要根据实际情况调整
    Mat binary;
    //CV_THRESH_BINARY代表阈值其中一种模式,下期会讲起阈值
    threshold(gray, binary, th, 255, CV_THRESH_BINARY);
    Mat red_binary;
    threshold(srcImage_R, red_binary, th, 255, CV_THRESH_BINARY);
    imshow("灰色图 + 阈值处理 ", binary);
    imshow("R通道+阈值处理", red_binary);
    //【6】将3个单通道重新合并成一个三通道图像  
    merge(channels_BGR, newImage);
    imshow("将R,G,B通道合并后的图像", newImage);
    waitKey(0);
    return 0;

}

6.总结

当然,这种分离通道+阈值分割的方法还可以用到其他场合,例如在红绿灯的检测上,也是可以借鉴这种方法的。

检测红灯

5.效果图.png

注意:当红章掩盖字体,这种方法无效

分享可以无数次,转载成自己文章QQ邮箱通知一下,未经授权请勿转载,明天见,司机下车。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 老师让我评价一下别人的一个跟踪效果,只有带跟踪框的视频,所以需要检测这个框,用了下投影,最早用matlab写的一个...
    和蔼的zhxing阅读 3,452评论 0 0
  • 一、分离颜色通道这个split函数的C++版本有两个原型,他们分别是: 关于变量介绍:第一个参数,InputArr...
    Zz鱼丸阅读 1,593评论 2 0
  • 前言opencv在图像处理中使用广泛,许多常见的应用场景例如人脸识别,车牌识别等都是基于opencv开发的。本文是...
    肖丹晨阅读 5,055评论 0 4
  • 我是上帝的喜剧演员。 最近开始写文章突然发现爱上写作了。写一个自我介绍吧,也方便对我感兴趣的朋友能多了解一下...
    胡老师要扯蛋阅读 565评论 17 16
  • pull away 离开 脱身 hissing hɪsɪŋ 发嘶嘶声 The snake mad...
    无奈柰阅读 92评论 0 1