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

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

一、关于图像修补

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


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


      但在日益智能化的今天,针对数字图像的修补工作逐渐由人工转向了自动化,这不仅节省了大量人工成本,而且计算机凭借优越的算法和庞大的数据库,对图像的修复效果更高效且优质。通过近几个月风风火火的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 干涉条纹图填补视频

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

1697720696832.png

图像修补算法示例视频1

3.2 地图填补视频

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

1697720653579.png

图像修补算法示例视频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++完整代码不免费分享,有意获取者可以私我。算法不是魔法,不能解决一切问题。该算法的核心逻辑可用于工程开发,但仍有许多需要结合实际完善的地方,不建议直接拷贝使用。

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

相关文章
|
3月前
|
机器学习/深度学习 算法 测试技术
低照度增强算法(图像增强+目标检测+代码)
低照度增强算法(图像增强+目标检测+代码)
96 1
|
2月前
|
机器学习/深度学习 算法 数据库
KNN和SVM实现对LFW人像图像数据集的分类应用
KNN和SVM实现对LFW人像图像数据集的分类应用
36 0
|
5月前
|
算法 数据挖掘 计算机视觉
Python利用K-Means算法进行图像聚类分割实战(超详细 附源码)
Python利用K-Means算法进行图像聚类分割实战(超详细 附源码)
166 0
|
5月前
|
算法 计算机视觉 异构计算
基于FPGA的图像形态学腐蚀算法实现,包括tb测试文件和MATLAB辅助验证
基于FPGA的图像形态学腐蚀算法实现,包括tb测试文件和MATLAB辅助验证
|
1天前
|
算法 TensorFlow 算法框架/工具
基于直方图的图像阈值计算和分割算法FPGA实现,包含tb测试文件和MATLAB辅助验证
这是一个关于图像处理的算法实现摘要,主要包括四部分:展示了四张算法运行的效果图;提到了使用的软件版本为VIVADO 2019.2和matlab 2022a;介绍了算法理论,即基于直方图的图像阈值分割,通过灰度直方图分布选取阈值来区分图像区域;并提供了部分Verilog代码,该代码读取图像数据,进行处理,并输出结果到&quot;result.txt&quot;以供MATLAB显示图像分割效果。
|
14天前
|
文字识别 算法 计算机视觉
图像倾斜校正算法的MATLAB实现:图像倾斜角检测及校正
图像倾斜校正算法的MATLAB实现:图像倾斜角检测及校正
21 0
|
2月前
|
存储 算法 算法框架/工具
基于HSV色度空间的图像深度信息提取算法FPGA实现,包含testbench和MATLAB辅助验证程序
该文档介绍了在一个FPGA项目中使用HSV色彩模型提取图像深度信息的过程。通过将RGB图像转换为HSV,然后利用明度与深度的非线性映射估计深度。软件版本为Vivado 2019.2和MATLAB 2022a。算法在MATLAB中进行了对比测试,并在FPGA上实现了优化,包括流水线并行处理和查找表技术。提供的Verilog代码段展示了RGB到灰度的转换。实验结果和核心程序的图片未显示。
|
2月前
|
机器学习/深度学习 算法 计算机视觉
利用深度学习算法实现图像风格转换技术探究
本文将通过深入分析深度学习算法在图像处理领域的应用,探讨如何利用神经网络实现图像风格转换技术。通过研究不同风格迁移算法的原理和实现方式,揭示其在艺术创作、图像编辑等领域的潜在应用和挑战。
|
2月前
|
编解码 算法 计算机视觉
基于FPGA的图像最近邻插值算法verilog实现,包括tb测试文件和MATLAB辅助验证
基于FPGA的图像最近邻插值算法verilog实现,包括tb测试文件和MATLAB辅助验证
|
3月前
|
机器学习/深度学习 算法 搜索推荐
【实操】数据扩增:Retinex算法用于图像颜色恢复和对比度增强
【实操】数据扩增:Retinex算法用于图像颜色恢复和对比度增强
34 0
【实操】数据扩增:Retinex算法用于图像颜色恢复和对比度增强