图片叠加是图像处理的基本操作。这个笔记是用来练习图像感兴趣区域ROI的。
ROI(Region of Interest) 是指图像中的一个矩形区域,表明后续的程序需要单独处理这一个小区域。如果对图像设置了ROI,那么,Opencv的大多数函数只在该ROI区域内运算(只处理该ROI区域,效果有点儿类似于对其他部分锁定不得编辑),如果没设ROI的话,就会处理整幅图像。需要注意的时候,设置的ROI一定在图像内部,而不能超出图像的范围。(超出了会怎样?没试过,可能会被重置为允许的图像最大值,有兴趣的同学可以试试看)
老版本中对图像设定ROI的函数是:
取消设定的ROI区域:
新的2.x版本则使用了更好的数据结构Mat来处理。所谓对src设置ROI其实是新建一个Mat header,但是data还是在src里面,这样操作ROI其实就是对原图像的操作。非常简单!
设置ROI:
设置了ROI,剪裁,拼接,叠加之类的操作就非常的简单了。
比如叠加到指定区域,
带透明的叠加,其中alpha,beta,gamma是透明度,double型(0~1),最终roi = roi*alpha + water_mark*beta + gama
ROI(Region of Interest) 是指图像中的一个矩形区域,表明后续的程序需要单独处理这一个小区域。如果对图像设置了ROI,那么,Opencv的大多数函数只在该ROI区域内运算(只处理该ROI区域,效果有点儿类似于对其他部分锁定不得编辑),如果没设ROI的话,就会处理整幅图像。需要注意的时候,设置的ROI一定在图像内部,而不能超出图像的范围。(超出了会怎样?没试过,可能会被重置为允许的图像最大值,有兴趣的同学可以试试看)
老版本中对图像设定ROI的函数是:
cvSetImageROI(IplImage* src,CvRect rect);
src表示的是源图像,rect只的是ROI区域。取消设定的ROI区域:
cvResetImageROI(src);
新的2.x版本则使用了更好的数据结构Mat来处理。所谓对src设置ROI其实是新建一个Mat header,但是data还是在src里面,这样操作ROI其实就是对原图像的操作。非常简单!
设置ROI:
Mat roi = Mat(src, Rect(x, y, width, height));
设置了ROI,剪裁,拼接,叠加之类的操作就非常的简单了。
比如叠加到指定区域,
water_mark.copyTo(roi);
带透明的叠加,其中alpha,beta,gamma是透明度,double型(0~1),最终roi = roi*alpha + water_mark*beta + gama
cv::addWeighted(roi, alpha, water_mark, beta, gamma, roi);
叠加英文文字,目前似乎不支持中文吧?
QDateTime time = QDateTime::currentDateTime();
QString time_str = time.toString("yyyy-MM-dd hh:mm:ss");
QString text = str+time_str;
cv::putText(image,text.toAscii().data(),Point(10,50),CV_FONT_HERSHEY_COMPLEX,0.5,Scalar(255,255,0));
如果要叠加中文文字,需要Qt的辅助:
重载paintEvent,并且使用QImage作为过渡,先在QImage上通过QPainter.drawText()绘制文字,用该QImage构造出QPixmap,然后通过drawPixmap绘制出叠加后的图片:
代码:
void MainWindow::paintEvent(QPaintEvent *event)
{
QPainter painter;
if(!text.isEmpty())
{
painter.begin(&qimg);
painter.setBrush(Qt::green);
painter.setFont(QFont("Times", 16, QFont::Bold));
painter.drawText(10,30, text);
painter.end();
}
pixmap = QPixmap::fromImage(qimg);
painter.begin(this);
painter.drawPixmap(250,50, pixmap);
painter.end();
}
效果图:
完整代码:
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <opencv/cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
void paintEvent(QPaintEvent *);
private slots:
void on_open_clicked();
void on_input_clicked();
void on_save_clicked();
private:
Ui::MainWindow *ui;
QPixmap pixmap;
QImage qimg;
QString text;
cv::Mat image;
};
#endif // MAINWINDOW_H
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPainter>
#include <QFileDialog>
#include <QDebug>
#include <QInputDialog>
#include <QDateTime>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
pixmap = QPixmap(512, 512);
pixmap.fill(Qt::white);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::paintEvent(QPaintEvent *event)
{
QPainter painter;
if(!text.isEmpty())
{
painter.begin(&qimg);
painter.setBrush(Qt::green);
painter.setFont(QFont("Times", 16, QFont::Bold));
painter.drawText(10,30, text);
painter.end();
}
pixmap = QPixmap::fromImage(qimg);
painter.begin(this);
painter.drawPixmap(250,50, pixmap);
painter.end();
}
void MainWindow::on_open_clicked()
{
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open Image"), ".",
tr("Image Files (*.png *.jpg *.jpeg *.bmp)"));
qimg.load(fileName);
update();
}
void MainWindow::on_input_clicked()
{
QString in = QInputDialog::getText(this, "Input your text", "Input");
QDateTime time = QDateTime::currentDateTime();
QString time_str = time.toString("yyyy-MM-dd hh:mm:ss");
text = in + "\n" + time_str;
qDebug() << text;
update();
}
void MainWindow::on_save_clicked()
{
QString fileName = QFileDialog::getSaveFileName(this,
tr("Open Image"),
".",
tr("Image Files (*.png *.jpg *.jpeg *.bmp)"));
qimg.save(fileName);
}