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

作者:翟天保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,                                  // OKERROR_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;						   // 梯度Xcv::Mat m_gradientY;						   // 梯度Yvector<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++完整代码不免费分享,有意获取者可以私我。算法不是魔法,不能解决一切问题。该算法的核心逻辑可用于工程开发,但仍有许多需要结合实际完善的地方,不建议直接拷贝使用。

       注意:当缺失的面积过大或者没有近似的窗口源数据时,填补效果会相对失真,这也是合理的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/34895.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pyecharts-Timeline讲解时间线

Pyecharts----Timeline (*^▽^*) 作者&#xff1a;发现美的眼睛&#xff08;本人&#xff09; 首先简单介绍一下pyecharts这个神奇的东东&#xff0c;如果你是从事web&#xff0c;那么Echarts就会熟悉知晓。 ——如果不是&#xff0c;那么这篇文章也会推荐一个非常好的&#x…

计算机网络英语作文150字,微信投票的英语,写一篇关于网络投票看法的英语作文150字左右...

你好微信投票的 Should students make friends online? Some people say yes Internet helps people make many friends Chatting on line, students can express their feelings and opinions more freely, and even get help for their foreign language studies Others, ho…

关于计算机500字英语作文,小学英语作文500字(共8篇)

小学英语作文500字由好范文网的会员“迈和”投稿精心推荐&#xff0c;小编希望以下多篇范文对你的学习工作能带来参考借鉴作用。 第1篇&#xff1a;小学英语作文500字 猜你正在找小学英语作文500字的怎么写&#xff1f;那么就给你这篇范文参考。 Im a happy girl.my english na…

关于计算机500字英语作文,500字英语作文范文

3 500字英语作文范文二 Protecting the Intangible Cultural Heritages Like tangible cultural heritages such as the Great Wall and the Forbidden City, intangible cultural heritages like Peking Opera and Confucius-commemorating rituals are equally crucial. We s…

Yarp项目代理ChatGPT,解决网络无法访问openAI的问题

1.创建Yarp项目 目的&#xff1a;通过代理解决网络无法访问openAI的问题 项目源码地址&#xff1a;https://github.com/raokun/YarpProject 1.创建.net7 webapi项目 创建一个webapi项目 2.搜索安装nuget包 1.搜索最新的Yarp.ReverseProxy包 https://www.nuget.org/package…

GPT-4 价值 20 美金的回复:是拯救还是毁灭?

编者注 - 周末闲着无聊&#xff0c;我们分别对比研究了 ChatGPT 2、3、4 版本的对话内容&#xff0c;结果发现&#xff0c;相较于前两个版本&#xff0c;第四版的精准度确实有所提高&#xff0c;但ChatGPT - 4 需要付费 20 美金。为了让这个发现更加有趣&#xff0c;我从网上挑…

【解决密码栏不显示】“可能是其他人在试图访问您的google账号....”

背景&#xff1a;Google浏览器上的账号自动退出了。 起因&#xff1a;自己又记成了邮箱的密码&#xff0c;多输入了几次&#xff0c;导致账号被锁不显示密码栏。 经过&#xff1a; 一、网上找了很多方法&#xff0c;有①重置②卸载等 二、我只重置了&#xff0c;但未卸载&a…

ORACLE锁定账户的原因及解决办法

工作中&#xff0c;发现一个ORACLE用户被锁定&#xff0c;查看状态如下图&#xff1a; profile可以用来对用户所能使用的数据库资源进行限制 查看monitor使用的profile&#xff1a; SELECT PROFILE FROM DBA_USERS WHERE USERNAMEMONITOR;结果如下&#xff1a; 查看对应的pro…

当提示“当前帐户被锁定,可能无法登录”时,如何解锁帐户?

解锁帐户的方法 错误提示解锁方法等待30分钟移除账户锁定阈值检查DNS设置设置密码永不过期清除缓存的凭据域环境中的帐户解锁错误提示 在登录电脑时,有时会出现如下登录错误的提示,我们可以按照以下几个方法来解锁账号。 解锁方法 等待30分钟 有一个设置用于配置输入错误…

关于oracle账户被锁定的解决办法

1.win r,输入cmd 2.输入sqlplus/nolog 3.输入conn/as sysdba 4.输入解锁语句&#xff1a;alter user 用户名 account unlock&#xff1b; 5.然后退出&#xff0c;输入用户名&#xff0c;密码&#xff0c;重新连接数据库成功

算力单位详解

TOPS TOPS是Tera Operations Per Second的缩写&#xff0c;1TOPS代表处理器每秒钟可进行一万亿次&#xff08;10^12&#xff09;操作。 与此对应的还有GOPS&#xff08;Giga Operations Per Second&#xff09;&#xff0c;MOPS&#xff08;Million Operation Per Second&…

到底什么是“算力”?

转载&#xff1a;到底什么是“算力”&#xff1f; 作者&#xff1a;小枣君 来源&#xff1a;鲜枣课堂&#xff08;ID&#xff1a;xzclasscom&#xff09; 这两年&#xff0c;算力可以说是ICT行业的一个热门概念。在新闻报道和大咖演讲中&#xff0c;总会出现它的身影。 那么&a…

ETH挖矿显卡算力大全

大家买显卡挖ETH&#xff0c;肯定最关心算力了&#xff0c;这里我整理一版&#xff0c;供大家参考&#xff0c;目前只有主流的整理上了&#xff0c;后期会完善更多的供大家参考&#xff01; 欢迎大家加入大力矿工群&#xff1a;621159725 软件下载&#xff1a;百度云盘链接…

GPU算力平台对比

对InsCode、智星云、恒源云、AutoDL以RTX 3090进行对比。 InsCode InsCode&#xff1a;https://inscode.csdn.net/gpu?utm_source260232576&spm1001.2014.3001.8290 智星云 智星云&#xff1a;http://gpu.ai-galaxy.cn/store?applicationAI%E4%BA%91%E5%AE%B9%E5%99…

世界超算最新排名出炉!

本文转载自程序员极客实验室 【导读】全球最新的超级计算机排名出炉&#xff0c;在TOP10榜单上变化不大&#xff0c;日本富岳凭借着领先第二名3倍的算力继续霸榜&#xff0c;不过从技术趋势来看&#xff0c;却有了新的变化。 在德国法兰克福举行的国际超级计算大会上&#xf…

【教程】腾讯云轻量应用服务器搭建聊天室

前言 前些日子听朋友说&#xff0c;他们领的腾讯云轻量246还在吃灰&#xff0c;我在萌备聊天室里看见了这个系统 感觉挺不错 那这篇文章就教大家用宝塔来搭建一个聊天室 介绍 Fiora系统非常简洁&#xff0c;而且也有很多功能&#xff0c;基于 node.js, mongodb, react 和 so…

云服务器搭建全过程(阿里云、腾讯云等...通用)

云主机LNMP环境搭建详解&#xff08;CentOS 6.9 64位系统&#xff09; 一、登录云主机 当购买云主机后会得到如下云主机信息 1.公网ip &#xff08;这里假设为 123.124.124.125 &#xff09;2.登录云主机的密码&#xff08;这里假设为 123456 &#xff09; 注&#xff1a; …

手把手带大家搭建一台服务器(腾讯云为例)

今天带大家入门如何搭建服务器&#xff0c;主要是面向小白读者。先说好&#xff0c;我自己也不是专业做后端的&#xff0c;只不过平时爱折腾点项目玩玩&#xff0c;所以有点小经验&#xff0c;本文就是基于这点小经验讲解的&#xff0c;如有不当之处还请谅解。 一、什么是服务器…

Unity 智能语音助手

Unity智能语音聊天机器人 在本篇文章中&#xff0c;使用了百度的语音识别、语音合成、智能对话Unit的功能&#xff0c;制作成了一款简易的聊天机器人&#xff0c;在开始做之前呢&#xff0c;需要确定需要实现的核心功能&#xff0c;有以下几点&#xff1a; &#xff08;1&…

PointNetGPD代码复现

0、安装分析 ps.应该安装pcl1.9tk8.1。这个导致后面python-pcl改了配置 Ubuntu版本pcl版本vtk版本18.041.9.18.2.0 1、pcl1.9安装 1.1 安装依赖 sudo apt-get update sudo apt-get install git build-essential linux-libc-dev sudo apt-get install cmake cmake-gui su…