OpenCV爬坑之路(二)——《OpenCV计算机视觉编程攻略》使用图像掩码问题

  • 一、出现问题
  • 二、问题解决
  • 1.问题原因
  • 2.解决方法
  • 3.相关知识点
  • 1.为啥是BGR,不是RGB格式
  • 2.灰度图像与彩色图像
  • 参考
  • 总结



一、出现问题

本人情况如下:

有下两图素材,将图2的smalllogo.png图插入到图1puppy.bmp中,并通过使用图像掩码实现只复制下面logo的白色部分,做到扣图的效果,但出现如图3的效果。

opencv计算机视觉实战 pdf opencv计算机视觉编程攻略_opencv

图1 puppy.bmp

opencv计算机视觉实战 pdf opencv计算机视觉编程攻略_#include_02

图2 smalllogo.png

opencv计算机视觉实战 pdf opencv计算机视觉编程攻略_opencv_03

图3 失败图

二、问题解决

1.问题原因

代码如下(示例):

#include "stdio.h"
#include<iostream> 
#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include<opencv2/imgproc/imgproc.hpp>

using namespace std;
using namespace cv;

int main()
{
	
	cv::Mat image = imread("images/puppy.bmp");//imread函数以【BGR形式】读取
	cv::Mat logo= imread("images/smalllogo.png",0);//以【灰度图形式】读取
	cv::Mat imageROI=image(
					cv::Rect(image.cols - logo.cols, //ROI coordinates
					image.rows - logo.rows,
					logo.cols, logo.rows));// ROI size
	cv::Mat mask(logo);//把标志作为掩码(必须是灰度图像)【罪魁祸首】
	logo.copyTo(imageROI,mask);//插入logo,只复制掩码不为0的位置
	imshow("logo", logo);
	imshow("image", image);
	imshow("imageROI", imageROI);
	cv::waitKey(300000);

原因是我看到“把标志作为掩码(必须是灰度图像)”,所以我把图2导入时将它作为一个灰度图像了,这就导致了后面的错误。图1为一个8UC3数据,而图2此时为一个8UC1数据,两者不同。

cv::Mat mask(logo);//把标志作为掩码(必须是灰度图像)【罪魁祸首】

2.解决方法

代码如下:

#include "stdio.h"
#include<iostream> 
#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include<opencv2/imgproc/imgproc.hpp>

using namespace std;
using namespace cv;

int main()
{
	
	cv::Mat image = imread("images/puppy.bmp");
	cv::Mat logo= imread("images/smalllogo.png");//【只有这里不同】
	cv::Mat imageROI=image(
					cv::Rect(image.cols - logo.cols, 
					image.rows - logo.rows,
					logo.cols, logo.rows));
	cv::Mat mask(logo);
	logo.copyTo(imageROI,mask);
	imshow("logo", logo);
	imshow("image", image);
	imshow("imageROI", imageROI);
	cv::waitKey(30000);

}

将图2中logo以imread函数直接读取。

opencv计算机视觉实战 pdf opencv计算机视觉编程攻略_opencv_04


图4 将图2logo以imread函数直接读取

opencv计算机视觉实战 pdf opencv计算机视觉编程攻略_opencv_05


图5 将图1与图2以灰度图形式读取

cv::Mat image = imread("images/puppy.bmp",0);
	cv::Mat logo= imread("images/smalllogo.png",0);

3.相关知识点

1.为啥是BGR,不是RGB格式


OpenCV是英特尔在1999年成立的,当时主流的摄像头制造商和软件供应商提供的摄像头采集的图像的通道排列顺序为BGR,位图BMP是最简单的,也是Windows显示图片的基本格式,其文件扩展名命名为*.bmp 。位图BMP(windows公司的标准格式)格式是BGR的。因为BGR在当时被广泛使用,早期的OpenCV开发者选择了BGR颜色格式,这已经成为今天使用的规范。

2.灰度图像与彩色图像


灰度图像(黑白图像)像素是8位无符号数(unsigned char),0为黑色,255表示白色。 彩色图像需要用三原色来重现不同的可见色。常用的主通道为红色、绿色和蓝色,因此每三个8位数值组成矩阵的一个元素,除了特殊的应用程序可能需要用16位通道(如医学图像),其他的8位通道就够了。


参考

1、
2、《OpenCV计算机视觉编程攻略》

总结


在学习图像掩码过程中,让我学习到了不同的类型的图像之间的差异。单通道图像与三通道图像之间的差异导致他们不能进行掩码操作。