基于等照度线和窗口匹配的图像修补算法

这篇具有很好参考价值的文章主要介绍了基于等照度线和窗口匹配的图像修补算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

基于等照度线和窗口匹配的图像修补算法

基于等照度线和窗口匹配的图像修补算法

一、关于图像修补

       图像修补的目的是基于已有的图像信息或数据库内信息,对缺失区域进行合理地修复。在诸多领域如电影、摄像、医疗等行业,有广泛的应用。

       传统上,图像修补由专业的修复师进行,修复师凭借自身丰富的工作经验和生活阅历,不仅能基于客观信息对图像缺失进行填充,更能进行主观创作,使得二次修复的图片更加生动形象。

       但在日益智能化的今天,针对数字图像的修补工作逐渐由人工转向了自动化,这不仅节省了大量人工成本,而且计算机凭借优越的算法和庞大的数据库,对图像的修复效果更高效且优质。通过近几个月风风火火的chatGPT,相信大家也看到了AI的魅力,这是未来的大趋势不可逆。

       针对图像修补,本文提出了一种基于等照度线和窗口匹配的图像修补算法,接下来将简单介绍下算法原理和流程,并展示相关的效果图。

二、算法原理和流程

       对图像缺失部分进行填充,首先要确定填充哪些内容,谁优先填充谁最后填充;其次要判断用什么数据来填充,能使得填充后的结果更贴近真实,显得不违和。做到了这两点,图像修补工作基本就完成了。

2.1 优先级计算

       我们先来讨论填充的优先级,如下图所示,图像白色部分是手动绘制的掩膜区域,该区域的真实信息被擦除了,我们现在要对其进行复原。

       在图中红线部分就是等照线,该线的两侧往往有较大的数值差异,因此它也与黑线所示的梯度线呈垂直关系;当等照线与掩膜边界呈垂直时,此时等照线上的像素点特征是非常强烈且明显的,通俗的讲,被填充的点极大可能和它那条等照线上的点类似,沿着这个等照线绘制下去,就可以了。

基于等照度线和窗口匹配的图像修补算法

       那我们怎么判断当前点是不是处于与掩膜边界垂直的等照线上呢?可以通过掩膜边界(黑线)的法线和红色等照度线这两个向量判断。等照线与掩膜边界垂直时,那与掩膜边界的法线自然平行,此时两个向量点乘可以使得值最大,因此该值可以作为填补优先级评判的指标,定义为D(x,y)。

基于等照度线和窗口匹配的图像修补算法

       除此之外,我们还需要用到一个指标,叫可信度,定义为C(x,y),就是被填补像素所在窗口内,源数据的占比,加入窗口为7*7的尺寸,里面有31个源数据,18个代填补数据,那它的可信度也就是31/49。可信度越高的像素,说明窗口内缺失的数据越少,对它们填补更容易且贴实。

       综上,代填补像素的优先级可以定义为P(x,y)=C(x,y)*D(x,y),当然也可以定义为别的,比如乘法变加法等等,大家可以自行发挥。

2.2 数据填充

       确认好代填补像素的优先级后,我们对优先级最高的像素所在窗口进行填充,填充基于窗口匹配实现。

       窗口匹配顾名思义就是从全图中寻找一个最像要填补的窗口的源数据窗口,把它粘过去即可。如下图所示,黑色窗口的实心部分是代填补窗口中的源数据,空心部分是代填补的数据。我们将黑色窗口实心部分和红色窗口实心部分进行三通道数据减法,对差值平方和累加取平均,可以得到一个匹配误差matchError,寻找全图最小的误差作为最小误差minError,此时对应的红色窗口就是匹配好的源数据。

基于等照度线和窗口匹配的图像修补算法

       但是,当出现两个同样的匹配误差后该怎么取舍呢?这时需要用到第二个匹配的指标——最小窗内方差minVarience。即对源数据中空心部分三通道数值求方差,数值减去平均值后平方和累加。方差低则说明数据平稳,不容易出现异常突兀的噪声数据,这样可以让填补的数据更贴实。

2.3 算法流程图

       综上,该算法的流程图可简化为:

基于等照度线和窗口匹配的图像修补算法

三、填补效果图

3.1 干涉条纹图填补视频

       该案例特征是图像黑白色系相对稳定,近似区域多,因此修补效果也是最好的。

图像修补算法示例视频1

3.2 地图填补视频 

       该案例特征是图像分为极大区域,如海洋、雪山、陆地、森林,色系复杂,图像细节多且杂。对其修补效果也是相对好的,因为本身糅杂的颜色系统中适当混入一些不和谐因素,凭借肉眼较难准确识别。

图像修补算法示例视频2

3.3 花卉修补

      该案例特征是图像色彩相对单调,花瓣区域纹理明显。这类图像色彩简单又不简单,颜色相近又各有区分,修补难度极大。经过图像修补后,可以发现花的边缘修补较成功,但是肉眼还是能看出内部区间存在一定的修补痕迹。

基于等照度线和窗口匹配的图像修补算法

基于等照度线和窗口匹配的图像修补算法

3.4 房屋修补

      该案例特征是房屋颜色与天空接近,此时填补区域如果是屋顶瓦砖,便补的很好,因为纹理缘故,匹配的数据也是瓦砖。

       但如果填补区域是屋顶侧面,则易出问题,若天空是蓝色还好,但恰巧天空也是棕黄色系,所以填补痕迹就突出了。

       该案例也是很不好找,特地找出来做评估。感兴趣的伙伴可以优化窗口匹配函数,比如全局和局部结合匹配等等。

基于等照度线和窗口匹配的图像修补算法

基于等照度线和窗口匹配的图像修补算法

四、代码分享

main.cpp

#include "Inpaint.h"

// 全局变量
int thickness = 5;
cv::Point sPoint(-1, -1);
cv::Mat image, mask;

// 鼠标事件
static void onMouse(int event, int x, int y, int flags, void*){
	if (event == cv::EVENT_LBUTTONUP || !(flags & cv::EVENT_FLAG_LBUTTON))
		sPoint = cv::Point(-1, -1);
	else if (event == cv::EVENT_LBUTTONDOWN)
		sPoint = cv::Point(x, y);
    else if( event == cv::EVENT_MOUSEMOVE && (flags & cv::EVENT_FLAG_LBUTTON)){
        cv::Point ePoint(x,y);
        if( sPoint.x < 0 )
            sPoint = ePoint;
        cv::line( mask, sPoint, ePoint, cv::Scalar::all(255), thickness);
        cv::line( image, sPoint, ePoint, cv::Scalar::all(255), thickness);
        sPoint = ePoint;
		cv::imshow("image", image);
    }
}

// 主函数
int main(){
	cv::Mat originalImage = cv::imread("6.jpg", 1);
	
	// 无输入图像
    if(!originalImage.data){
		cout << "Error unable to open input image" << endl;
        return 0;
    }

	// 拷贝图像
    image=originalImage.clone();
	mask = cv::Mat::zeros(image.size(), CV_8U);

	// 设置鼠标事件
	cv::namedWindow("image", 1);
	cv::imshow("image", image);
	cv::setMouseCallback("image", onMouse, 0);

	// 循环处理
	while(true){
		// 键盘事件
		char key = (char)cv::waitKey();

		// 按'b'跳出循环,结束程序
		if (key == 'b')
			break;

		// 按'r'恢复原始图像
		if (key == 'r'){
			mask = cv::Scalar::all(0);
			image = originalImage.clone();
			cv::imshow("image", image);
		}

		// 按'空格'执行算法
		if (key == ' '){
			int r = 3;
			InpaintAlgorithm *m_algorithm = new InpaintAlgorithm(image, mask, 2 * r + 1, TEMPLATE_MATCHING);
			m_algorithm->executeInpaint();
			cv::namedWindow("result");
			cv::imshow("result", m_algorithm->m_outputImage);
		}

		// 按'w'增加画笔厚度
		if (key == 'w') {
			thickness++;
			if (thickness > 20)
				thickness = 20;
			cout << "Thickness = " << thickness << endl;
		}

		// 按's'减少画笔厚度
		if (key == 's') {
			thickness--;
			if (thickness < 1)
				thickness = 1;
			cout << "Thickness = " << thickness << endl;
		}
	}
    return 0;
}

Inpaint.h

#ifndef INPAINT_H
#define INPAINT_H
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/photo/photo.hpp"

using namespace std;
using namespace cv;

// 填补策略
enum INPAINT_METHOD {
	TEMPLATE_MATCHING,                              // 模板匹配
};

// 错误类型
enum ERROR_TYPE {
	ERROR_TYPE_OK,                                  // OK
	ERROR_TYPE_INPUT,								// 输入图像异常
	ERROR_TYPE_MASK,								// 掩膜异常
	ERROR_TYPE_WINDOWSIZE,							// 窗尺寸异常
};

// 定义图像填补接口
class Inpaint
{
public:
	// 构造函数
	Inpaint(cv::Mat inputImage, cv::Mat mask, int windowSize);

	// 检查异常
	void checkError();

	// 执行
	virtual void execute() = 0;

public:
	ERROR_TYPE errorType;                           // 错误码
	int m_windowSize = 9;                           // 窗尺寸
	cv::Mat m_inputImage;							// 输入图像
	cv::Mat m_mask;									// 掩膜
	cv::Mat m_outputImage;							// 输出图像
};

// 实现具体策略-模板匹配
class TemplateMatching :public Inpaint
{
public:
	// 构造函数
	TemplateMatching(cv::Mat inputImage, cv::Mat mask, int windowSize);

	// 执行
	virtual void execute();

private:
	// 初始化
	void init();

	// 检查是否存在未填补信息
	bool checkUnfilled();
	
	// 寻找目标位置集合
	void findTargetPoints();

	// 计算可信度
	void calcConfidence();

	// 获取优先级
	void getPriority();

	// 寻找最佳匹配
	void findBestMatch();

	// 更新图像
	void updateImage();

private:
	int targetIndex;							   // 目标点序号
	cv::Point2i m_bestMatchUL;					   // 最佳匹配点左上角位置
	cv::Mat m_updatedImage;                        // 更新中的图像
	cv::Mat m_updatedMask;						   // 更新中的掩膜
	cv::Mat m_confidence;						   // 可信度
	cv::Mat m_oriSourceRegion;					   // 原始源位置
	cv::Mat m_sourceRegion;						   // 源位置
	cv::Mat m_targetRegion;						   // 目标位置
	cv::Mat m_gradientX;						   // 梯度X
	cv::Mat m_gradientY;						   // 梯度Y
	vector<cv::Point2i> targetPoints;			   // 目标位置点集合
	vector<pair<float, float>> normals;            // 法线集合
};

// 应用类-图像修补算法调用
class InpaintAlgorithm
{
public:
	// 构造函数
	InpaintAlgorithm(cv::Mat inputImage, cv::Mat mask, int windowSize, INPAINT_METHOD method);

	// 析构函数
	~InpaintAlgorithm();

	// 设置修补策略
	void setInpaintAlgorithm(INPAINT_METHOD method);

	// 执行图像修补
	void executeInpaint();

public:
	int m_windowSize;							   // 窗尺寸
	cv::Mat m_inputImage;						   // 输入图像
	cv::Mat m_mask;								   // 掩膜
	cv::Mat m_outputImage;                         // 输出图像

private:
	Inpaint* m_inpaint;							   // 图像填补类实例
};

#endif

       C++完整代码不免费分享,有意获取者可以私我。算法不是魔法,不能解决一切问题。该算法的核心逻辑可用于工程开发,但仍有许多需要结合实际完善的地方,不建议直接拷贝使用。

       注意:当缺失的面积过大或者没有近似的窗口源数据时,填补效果会相对失真,这也是合理的。文章来源地址https://www.toymoban.com/news/detail-440795.html

到了这里,关于基于等照度线和窗口匹配的图像修补算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【计算机视觉、关键点检测、特征提取和匹配】基于SIFT、PCA-SIFT和GLOH算法在不同图像之间建立特征对应关系,并实现点匹配算法和图像匹配(Matlab代码实现)

    💥💥💞💞 欢迎来到本博客 ❤️❤️💥💥 🏆博主优势: 🌞🌞🌞 博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️ 座右铭: 行百里者,半于九十。 📋📋📋 本文目录如下: 🎁🎁🎁 目录 💥1 概述 📚2 运行结果 🎉3 参考文献 🌈4 Matlab代码、数据、文章

    2024年03月14日
    浏览(55)
  • 图像分割--点、线和边缘检测

    图像分割是指将图像细分为构成它的子区域或物体 本章算法基于灰度值的两个基本性质之一:不连续性和相似性 就像局部平均平滑一幅图像那样,假设平均处理类似于积分,对于灰度的突变,局部变化可以用微分来检测 使用空间滤波器来计算图像中每个像素位置处的一阶导

    2024年02月09日
    浏览(48)
  • 低照度图像数据集

    LSRW、  https://docs.activeloop.ai/datasets 【LOL】:paper,包含低光/正常光图像的 配对 数据集  包含 500 个低光/正常光图像对。 原始图像被调整为 400×600 并转换为便携式网络图形格式。 使用三步法来消除数据集中图像对之间的错位。  【Exclusive Dark】:paper, Exclusive Dark数据集仅由

    2024年02月05日
    浏览(40)
  • Inpaint Anything:一键进行多种图像修补

    本文分享自华为云社区《绘制一切》,作者: 雨落无痕 。 相关链接: Notebook案例地址:绘制一切 AI Gallery:https://developer.huaweicloud.com/develop/aigallery/home.html 也可通过AI Gallery,搜索【绘制一切】一键体验! 通过一键点击标记选定对象,即可实现移除指定对象、填补指定对象、

    2024年02月15日
    浏览(66)
  • 【论文笔记】—低照度图像增强—Unsupervised—EnlightenGAN—2019-TIP

    EnlightenGan是第一个成功地将 非配对训练 引入微光图像增强的工作。  基于深度学习的方法在图像恢复和增强方面取得了显著的成功,但是在缺乏配对训练数据的情况下它们仍然具有竞争力吗?  使用从输入本身提取的信息来规范非配对训练,而不是使用ground truth数据监督学

    2024年02月07日
    浏览(40)
  • 无人机航拍图像匹配——SIFT算法实践(含代码)

    SIFT(Scale-Invariant Feature Transform)算法是由David Lowe于1999年提出的一种用于图像处理和计算机视觉中的特征提取和匹配方法。它在航拍图像匹配中具有重要的意义,主要体现在以下几个方面: 尺度不变性 :航拍图像通常具有大范围的尺度变化,例如拍摄距离目标较远或较近的

    2024年02月04日
    浏览(50)
  • OpenCV实战(21)——基于随机样本一致匹配图像

    当两台摄像机拍摄同一场景时,它们会在不同视角拍摄到相同的元素。我们已经学习了特征点匹配,在本节中,我们将学习如何利用两个视图之间的对极约束来更可靠地匹配图像特征。 我们将遵循以下原则:当匹配两个图像之间的特征点时,只接受落在相应极线上的匹配。为

    2024年02月05日
    浏览(67)
  • SIFT 算法 | 如何在 Python 中使用 SIFT 进行图像匹配

    人类通过记忆和理解来识别物体、人和图像。你看到某件事的次数越多,你就越容易记住它。此外,每当一个图像在你的脑海中弹出时,它就会将该项目或图像与一堆相关的图像或事物联系起来。如果我告诉你我们可以使用一种称为 SIFT 算法的技术来教机器做同样的事情呢?

    2024年02月13日
    浏览(42)
  • 低照度图片增强——传统算法

    光照因素一直是影响成像质量的一个关键因素,夜间等光照环境较差的条件下的图片往往细节丢失、分辨不清,信噪比低下。低照度图像增强是指通过一系列算法和技术,增强在低照度或弱光条件下拍摄的图像的可视化质量。本文主要介绍一些传统的低照度图像增强算法,给

    2024年02月08日
    浏览(42)
  • 基于SIFT图像特征识别的匹配方法比较与实现

    目前常用的匹配器有 BFMatcher and FlannBasedMatcher 1.1 BFMatcher BFMatcher 全称是 Brute-Force Matcher (直译即为暴力匹配器) 大致原理: 对于 img1 中的每个描述符, BFMatcher 将其与 img2 中的所有描述符进行比较;它计算两个描述符之间的距离度量(例如,欧几里得距离或汉明距离,默认使

    2024年02月09日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包