• CG——Possion Image Editing


    博主终于正式回来发文了。

    之后会写一些学习心得,大学应该不会打ACM了。

    目前尝试CG,兴趣使然,希望后面可以坚持吧。

    Possion Image Editing

    学习资料:https://blog.csdn.net/u011534057/article/details/68922319

    https://zhuanlan.zhihu.com/p/58867397

    这两份讲的比较好,但还是看论文比较好,我按第一篇又是算梯度又是算散度,又在想怎么构造转移矩阵,对自己的数学极度怀疑,差点自闭掉。后来经jdr大佬指点发现按照论文的分析,这实际就是一个解方程组的问题,即  div(h) = div(g), 明显是一个高斯消元的方程,但是图像以像素点储存,复杂度明显爆炸,所以可以用迭代的方式解,因为边界是确定的,最后会收敛,复杂度暴降。

    简单概括一下泊松:讲目标图像抽象成一个函数h,背景设为f,融合后的图像设为g,我们所做的就是让g看起来就是f上的一个函数。对策就是边界取f的值,g的变化趋势尽量符合h的变化趋势。即

    遇到的问题:

    1.opencv的c++安装:花了两天都没搞定,按照博客一步步做,但是我下载的文件夹和博客下下来的不一样,最后无法写codevs的路径。(中途又在gcc的编译路径中加了空格,真是佩服我自己)=》最后只有选择Python写。(最后意识到我Python烂到和装环境差不多)

    2.算法:按照博客老实按论文公式写,对数学要求太高了,好多人居然用到fft...=》请教jdr获得迭代解方程的算法

    3.Python运算太慢,迭代还是T=》只有把数据传到C++来处理,果然还是得C

    4.图像坐标轴问题,图像的表示是mat[y][x],这个搞了也挺久的,到处改(顺带一提,Python我用了个for x in,和后面的x变量命名重了,这个bug找的也真的久,写Python真的要注意变量范围,这比C++难多了)

    5.多边形选取:最开始搞的ROI是矩形区域,做出来明显有问题,去网上学UI做了一个mask的操作,关于mask要注意区分3个图的坐标表示

    6.其他细节:迭代事可能会爆值,结束后判255与0,中间判会增加误差;numpy中array用法不能和list等级,对于array, a[i][j] = [0,0,0]是错误写法,只能写成 a[i][j].all == 0; 对于list, a[i][j] == [0, 0, 0] 返回的是[True, True, True].

    算法的局限:

    1.背景图像选取应避免边缘截断,目标图像的背景色应和背景的颜色相近

    2.使用混合梯度可以使边缘更加圆滑,但是可能会造成颜色变暗,论文后来进行了调色

    3.选取图像本身有噪音或者色彩值比较极端经处理后缺陷会放大(网图有些看着正常,但实际颜色和肉眼观察不符,而且网图有很多也是合成的,要注意

    原代码及成品:

    python处理:

    import cv2
    import matplotlib.pyplot as plt
    import numpy as np
    import math
    %matplotlib inline
    
    def cv_show(name, img):
        cv2.imshow(name, img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    
        
    lsPointsChoose = []
    tpPointsChoose = []
    pointsCount = 0
    count = 0
    Y, X = 0, 0
    pointsMax = 6
    lenx, leny = 0, 0
    x1, y1, = 0, 0
    centerx, centery = 0, 0
    flag = esc = False
    img = cv2.imread('ren2.jpg') #读取图像
    dst = cv2.imread("ren1.jpg")
    
    # 图像大小处理
    h, w = dst.shape[:2]
    # dst = cv2.resize(dst, (int(w*0.8), int(h*0.8)) )
    img = cv2.resize(img, (int(w), int(h)) )
    
    tmp = img.copy()
    img2 = img.copy()
    tmp3 = img.copy()
    tmp2 = dst.copy()
    
    fhand = open('data.txt','w')
    cv2.namedWindow('getROI')
    cv2.setMouseCallback('getROI',getROI)
    
    cv2.namedWindow('background')
    cv2.imshow('background', dst)
    cv2.setMouseCallback('background', getcenter)
    while(1):
      cv2.imshow('getROI',img)
      if cv2.waitKey(1)&0xFF==ord("e"): 
         cv2.destroyAllWindows()
         break
    fhand.close()
    main part
    def isout(x, y):
        if (mask2[x][y][0] == 0) :
            return True
        if (mask2[x+1][y][0] == 0):
            return True
        if (mask2[x-1][y][0] == 0):
            return True
        if (mask2[x][y+1][0] == 0):
            return True
        if (mask2[x][y-1][0] == 0):
            return True
        return False
        
    def handle(mat, x, y, lenx, leny, laparr):
            global fhand
            for x__ in laparr:
                fhand.write(str(x__))
                fhand.write(' ')
            for i in range(y, leny+y):
                for j in range(x, x+lenx):
                    fhand.write(str(mat[i][j])+' ')
                        
    def getLap(mat, x, y, lenx, leny, t):
        ans = list()
        u = 0
        print('lap',centerx,centery)
        for i in range(y, y+leny):
            for j in range(x, lenx+x):
                if isout(i, j):
                    pass
                else:
                    u = (mat[i][j]*4 - mat[i][j-1] - mat[i][j+1] - mat[i-1][j] - mat[i+1][j])
    #                 混合梯度:
    #                 v = (t[i-y+centery][j-x+centerx]*4 - t[i-y+centery][j-1-x+centerx] - t[i-y+centery][j+1-x+centerx] - t[i-1-y+centery][j-x+centerx] - t[i+1-y+centery][j-x+centerx])
    #                 if abs(v) > abs(u):
    #                     u = v
    #                 print('ccc',u,v)
                ans.append(u)
        return ans
    
    
    def display(x, y, lenx, leny):
        global X, Y
        X = x
        Y = y
    
        global tmp, tmp2, fhand, mask2, tmp3
        fhand.write(str(lenx))
        fhand.write(' ')
        fhand.write(str(leny))
        fhand.write('
    ')
    
        for i in range(y, y+leny):
            for j in range(x, lenx+x):
                fhand.write(str(mask2[i][j][0]) + ' ')    
                
        B,G,R = cv2.split(tmp)#imge   
        b,g,r=cv2.split(tmp2)#background
        
        B = getLap(B, x, y, lenx, leny, b)
        G = getLap(G, x, y, lenx, leny, g)
        R = getLap(R, x, y, lenx, leny, r)
    #     print('display',centerx, centery)
        
        handle(b, centerx, centery, lenx, leny, B)
        handle(g, centerx, centery, lenx, leny, G)
        handle(r, centerx, centery, lenx, leny, R)
        
    the core of possion

    C++迭代处理数据:

    #include<bits/stdc++.h>
    using namespace std;
    vector <double> sandu[3], mat[3];
    vector <int> mask;
    int lenx, leny, size;
    vector <bool> vis;
    
    int fix(int x){
        //防止爆值
        if(x > 255)return 255;
        if(x < 0)return 0;
        return x;
    }
    
    bool isout(int x, int y){
        // bool fg = 1;
        int idx = x * lenx + y;
        // if(mat[0][idx] == 1 && mat[1][idx] == 1 && mat[2][idx] == 1)return 0;
        // return 1;
        
        if(mask[idx] == 0) return 1;
        
        int dir[5] = {-1,1,lenx,-lenx};
        for(int i = 0; i < 4; i++){
            // fg = 1;
            int nw = idx + dir[i];
            if(nw < 0 || nw >= size)continue;
            if(mask[idx] == 0)return 1;
        }
        return 0;
    }
    
    int main(){
        freopen("data.txt","r",stdin);
        freopen("result1.txt","w",stdout);
        
        cin>>lenx>>leny;
        size=lenx*leny;
        for(int i = 0; i < size; i++){
            int u; scanf("%d", &u); mask.push_back(u);
        }
        for(int t = 0; t < 3; t++){
            int u;
            for(int i = 1; i <= size; i++){
                scanf("%d", &u); sandu[t].push_back(u*1.0);
            }
            for(int i = 1; i <= size; i++){
                scanf("%d", &u); mat[t].push_back(u*1.0);
            }
        }
        for(int i = 0; i < leny; i++)
            for(int j = 0; j < lenx; j++){
                bool v = isout(i, j);
                vis.push_back(v);
                // if(v) printf("%d %d
    ",i,j);
            }
        int cnt=0;
        for(int t = 0; t < 3; t++){
            bool fg = 1;
            while(fg){
                fg = 0;cnt++;
                for(int i = 0; i < leny; i++)
                    for(int j = 0; j < lenx; j++){
                        int idx = i * lenx + j;
                        if(vis[idx])continue;
                        double nw = (sandu[t][idx] + mat[t][idx-1] + mat[t][idx+1] + mat[t][idx-lenx] + mat[t][idx+lenx]) / 4;
                        // if(nw > 255) nw = 255;
                        // if(nw < 0) nw = 0;
                        if(abs(nw - mat[t][idx]) > 1e-4)fg = 1;
                        mat[t][idx] = nw;
                        
                    }
            }
        }
        
        printf("[");
        for(int i = 0; i < leny; i++){
            printf("[");
            for(int j = 0; j < lenx; j++){ 
                int b = fix(int(mat[0][i*lenx+j])); 
                int g = fix(int(mat[1][i*lenx+j])); 
                int r = fix(int(mat[2][i*lenx+j])); 
                printf("[%d,%d,%d]", b, g, r);
                if(j != lenx - 1)printf(", ");
            }
            printf("]");
            if(i != leny - 1)printf(",
    ");
            else printf("
    ");
        }
        printf("]");
    }
    View Code

    Python处理

    def getans(a, b):
        global dst
        cnt = 0
        cnt2 = 0
        centerx, centery = a, b
        print(a,b)
        res = open("result.txt","r")
        w = res.read()
        res.close()
        w = eval(w)
        for i in range(centery, centery + leny):  
            for j in range(centerx, centerx + lenx):
                if not isout(Y+i-centery, X+j-centerx):
                    dst[i][j] = w[i-centery][j-centerx]
                    cnt2 += 1
                else:
                    cnt += 1
        print(cnt,cnt2)
        cv_show('ret',dst)
    #     print(cnt, cnt2)
    getans(centerx,centery)    
    output image

    成品:

  • 相关阅读:
    【零售业集成系列】消费积分的会计处理到SAP系统实现
    SAP S4 ECC EPIC 'Month 00 not Plausible'. upload bank receipt error msg
    [OHIF-Viewers]医疗数字阅片-医学影像-Module: Panel-自定义面板-中-es6-Object.defineProperty()定义属性
    [OHIF-Viewers]医疗数字阅片-医学影像-Module: Panel-自定义面板-上
    [Chrome 83]谷歌浏览器升级后对表单控件和焦点元素黑框取消掉方法,磕碜啦啦的难看死了-chrome://flags/#form-controls-refresh
    [OHIF-Viewers]医疗数字阅片-医学影像-REACT向事件处理程序传递参数-.bind-传递函数给组件
    [OHIF-Viewers]医疗数字阅片-医学影像-es6解构赋值-const{}=-let{}=
    [OHIF-Viewers]医疗数字阅片-医学影像-Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。_.throttle(func, [wait=0], [options={}])实例解析防抖动(Debouncing)和节流阀(Throttling)
    [OHIF-Viewers]医疗数字阅片-医学影像-数字胶片直接下载,不再弹窗进行设置
    [OHIF-Viewers]医疗数字阅片-医学影像-ViewportDownloadForm.js
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/14856515.html
Copyright © 2020-2023  润新知