代码之家  ›  专栏  ›  技术社区  ›  Fabiano Taioli

Opencv中高斯函数的GIMP差分

  •  0
  • Fabiano Taioli  · 技术社区  · 7 年前

    我想复制GIMP过滤器>边缘检测>利用OpenCV实现C++中的高斯差异

    我找到了这个用于DOG实现的简单代码,但我希望GIMP的两个参数Raidus1和Radius2的结果相同。

    Mat g1, g2, result;
    Mat img = imread("test.png", CV_LOAD_IMAGE_COLOR); 
    GaussianBlur(img, g1, Size(1,1), 0);
    GaussianBlur(img, g2, Size(3,3), 0);
    result = g1 - g2;
    

    如何将2个radius参数添加到实现中?

    样本输入图像 enter image description here

    Params enter image description here

    输出 enter image description here

    如果能帮上忙,这是链接到C实现的过滤器

    https://gitlab.gnome.org/GNOME/gimp/blob/master/plug-ins/common/edge-dog.c

    0 回复  |  直到 7 年前
        1
  •  1
  •   Mark Setchell    7 年前

    我不知道答案,但已经没有头发了——请看评论。我一直在做这个,有一些代码不起作用,但比我更聪明的人谁不想写代码,可能能够看到什么是错误的,所以我想我会分享我所拥有的。我对任何一点都不感兴趣,所以欢迎任何人采纳并修改这一点,并给出一个有效的答案。如果我们能找到解决办法,我很好。我用Python做的,但是我确信如果我们能得到一些有用的东西,我们可以很容易地把任何Python改编成C++。

    #!/usr/bin/env python3
    
    import numpy as np
    import math
    import cv2
    
    def radius2stdev(radius):
        """
        Return std deviation corresponding to a given radius.
        I got this from: https://gitlab.gnome.org/GNOME/gimp/blob/master/plug-ins/common/edge-dog.c
        """
        stdev  = math.sqrt (-(radius * radius) / (2 * math.log (1.0 / 255.0)));
        return stdev
    
    # Load image, make float and scale to range 0..1
    im = cv2.imread("image.jpg",cv2.IMREAD_COLOR).astype(np.float)
    im = im/255.0
    
    stdev1  = radius2stdev(22.0)
    stdev2  = radius2stdev(5.0)
    
    print('Stdev1: {}'.format(stdev1))
    print('Stdev2: {}'.format(stdev2))
    
    # Generate the two Gaussians and their difference
    # I believe OpenCV calculates the size of the kernel to match the std dev if you pass no kernel size
    # See https://docs.opencv.org/3.4.1/d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1
    
    g1 = cv2.GaussianBlur(im,(0,0),stdev1,stdev1)
    g2 = cv2.GaussianBlur(im,(0,0),stdev2,stdev2)
    result = g1 -g2
    
    # Multiply back up by 255 and save as PNG
    result = (result * 255).astype(np.uint8)
    cv2.imwrite("result.png", result)
    
    # Normalize and save normalised too
    resultn = cv2.normalize(result,None,alpha=0,beta=255,norm_type=cv2.NORM_MINMAX)
    cv2.imwrite("result-n.png", resultn)
    

    标准偏差打印如下:

    Stdev1: 6.608505869104614
    Stdev2: 1.5019331520692305
    

    我相信你的半径显示的22000和5000只是你国际化的结果,它们对应于美国/英国格式的22.0和5.0。


    我也尝试过 ImageMagick 在命令行上得到了一些模糊的相似之处,尽管我不确定这证明了什么:

    magick image.jpg -morphology Convolve DoG:0,20,5 -evaluate multiply 6 result.jpg
    

    enter image description here

        2
  •  0
  •   Schroeder    6 年前

    看起来好像漏了一行。 从…起 lines 729-730 of edge-dog.c :

      radius = fabs (radius) + 1.0;
      std_dev = sqrt (-(radius * radius) / (2 * log (1.0 / 255.0)));
    

    然后,Gimp将高斯函数计算为make_曲线(std_dev,…)中的整数列表。笔记