python - Python OpenCV 中的阴影去除

标签 python image opencv shadows

我正在尝试使用 Finlayson 等人的熵最小化方法在 python OpenCV 中实现阴影去除。其他:

"Intrinsic Images by Entropy Minimization", Finlayson, et. al.

我似乎无法匹配论文中的结果。我的熵图与论文中的不匹配,我得到了错误的最小熵。

有什么想法吗? (根据要求我有更多的源代码和论文)

#############
# LIBRARIES
#############
import numpy as np
import cv2
import os
import sys
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
from PIL import Image
import scipy
from scipy.optimize import leastsq
from scipy.stats.mstats import gmean
from scipy.signal import argrelextrema
from scipy.stats import entropy
from scipy.signal import savgol_filter

root = r'\path\to\my_folder'
fl = r'my_file.jpg'

#############
# PROGRAM
#############
if __name__ == '__main__':

    #-----------------------------------
    ## 1. Create Chromaticity Vectors ##
    #-----------------------------------

    # Get Image
    img = cv2.imread(os.path.join(root, fl))
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    h, w = img.shape[:2]

    plt.imshow(img)
    plt.title('Original')
    plt.show()

    img = cv2.GaussianBlur(img, (5,5), 0)

    # Separate Channels
    r, g, b = cv2.split(img) 

    im_sum = np.sum(img, axis=2)
    im_mean = gmean(img, axis=2)

    # Create "normalized", mean, and rg chromaticity vectors
    #  We use mean (works better than norm). rg Chromaticity is
    #  for visualization
    n_r = np.ma.divide( 1.*r, g )
    n_b = np.ma.divide( 1.*b, g )

    mean_r = np.ma.divide(1.*r, im_mean)
    mean_g = np.ma.divide(1.*g, im_mean)
    mean_b = np.ma.divide(1.*b, im_mean)

    rg_chrom_r = np.ma.divide(1.*r, im_sum)
    rg_chrom_g = np.ma.divide(1.*g, im_sum)
    rg_chrom_b = np.ma.divide(1.*b, im_sum)

    # Visualize rg Chromaticity --> DEBUGGING
    rg_chrom = np.zeros_like(img)

    rg_chrom[:,:,0] = np.clip(np.uint8(rg_chrom_r*255), 0, 255)
    rg_chrom[:,:,1] = np.clip(np.uint8(rg_chrom_g*255), 0, 255)
    rg_chrom[:,:,2] = np.clip(np.uint8(rg_chrom_b*255), 0, 255)

    plt.imshow(rg_chrom)
    plt.title('rg Chromaticity')
    plt.show()

    #-----------------------
    ## 2. Take Logarithms ##
    #-----------------------

    l_rg = np.ma.log(n_r)
    l_bg = np.ma.log(n_b)

    log_r = np.ma.log(mean_r)
    log_g = np.ma.log(mean_g)
    log_b = np.ma.log(mean_b)

    ##  rho = np.zeros_like(img, dtype=np.float64)
    ##
    ##  rho[:,:,0] = log_r
    ##  rho[:,:,1] = log_g
    ##  rho[:,:,2] = log_b

    rho = cv2.merge((log_r, log_g, log_b))

    # Visualize Logarithms --> DEBUGGING
    plt.scatter(l_rg, l_bg, s = 2)
    plt.xlabel('Log(R/G)')
    plt.ylabel('Log(B/G)')
    plt.title('Log Chromaticities')
    plt.show()

    plt.scatter(log_r, log_b, s = 2)
    plt.xlabel('Log( R / 3root(R*G*B) )')
    plt.ylabel('Log( B / 3root(R*G*B) )')
    plt.title('Geometric Mean Log Chromaticities')
    plt.show()

    #----------------------------
    ## 3. Rotate through Theta ##
    #----------------------------
    u = 1./np.sqrt(3)*np.array([[1,1,1]]).T
    I = np.eye(3)

    tol = 1e-15

    P_u_norm = I - u.dot(u.T)
    U_, s, V_ = np.linalg.svd(P_u_norm, full_matrices = False)

    s[ np.where( s <= tol ) ] = 0.

    U = np.dot(np.eye(3)*np.sqrt(s), V_)
    U = U[ ~np.all( U == 0, axis = 1) ].T

    # Columns are upside down and column 2 is negated...?
    U = U[::-1,:]
    U[:,1] *= -1.

    ##  TRUE ARRAY:
    ##
    ##  U = np.array([[ 0.70710678,  0.40824829],
    ##                [-0.70710678,  0.40824829],
    ##                [ 0.        , -0.81649658]])

    chi = rho.dot(U) 

    # Visualize chi --> DEBUGGING
    plt.scatter(chi[:,:,0], chi[:,:,1], s = 2)
    plt.xlabel('chi1')
    plt.ylabel('chi2')
    plt.title('2D Log Chromaticities')
    plt.show()

    e = np.array([[np.cos(np.radians(np.linspace(1, 180, 180))), \
                   np.sin(np.radians(np.linspace(1, 180, 180)))]])

    gs = chi.dot(e)

    prob = np.array([np.histogram(gs[...,i], bins='scott', density=True)[0] 
                      for i in range(np.size(gs, axis=3))])

    eta = np.array([entropy(p, base=2) for p in prob])

    plt.plot(eta)
    plt.xlabel('Angle (deg)')
    plt.ylabel('Entropy, eta')
    plt.title('Entropy Minimization')
    plt.show()

    theta_min = np.radians(np.argmin(eta))

    print('Min Angle: ', np.degrees(theta_min))

    e = np.array([[-1.*np.sin(theta_min)],
                  [np.cos(theta_min)]])

    gs_approx = chi.dot(e)

    # Visualize Grayscale Approximation --> DEBUGGING
    plt.imshow(gs_approx.squeeze(), cmap='gray')
    plt.title('Grayscale Approximation')
    plt.show()

    P_theta = np.ma.divide( np.dot(e, e.T), np.linalg.norm(e) )

    chi_theta = chi.dot(P_theta)
    rho_estim = chi_theta.dot(U.T)
    mean_estim = np.ma.exp(rho_estim)

    estim = np.zeros_like(mean_estim, dtype=np.float64)

    estim[:,:,0] = np.divide(mean_estim[:,:,0], np.sum(mean_estim, axis=2))
    estim[:,:,1] = np.divide(mean_estim[:,:,1], np.sum(mean_estim, axis=2))
    estim[:,:,2] = np.divide(mean_estim[:,:,2], np.sum(mean_estim, axis=2))

    plt.imshow(estim)
    plt.title('Invariant rg Chromaticity')
    plt.show()

输出:

Original

rg Chromaticity

Log Chromaticities

Geometric Mean Log Chromaticities

2D Geometric Log Chromaticities

Entropy Minimization

Grayscale Approximation

Invariant rg Chromaticity

最佳答案

Shadow Removal Using Illumination Invariant Image Formation (Ranaweera, Drew)结果和讨论下的注释指出,由于 JPEG 压缩,JPEG 图像和 PNG 图像的结果不同。因此,期待与“熵最小化的内在图像”(Finlayson 等人)所显示的结果完全相同可能是不合理的。

我还注意到您没有添加作者在其他论文中推荐的“额外光线”。

此外,在定义 rg_chrom 时, channel 的顺序需要是 BGR 而不是像您使用的 RGB。

我正在努力实现这篇论文,所以您的代码对我非常有用。谢谢你

关于python - Python OpenCV 中的阴影去除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47745541/

相关文章:

c++ - OpenCV 3双边滤波器函数错误

java - 无法用java opencv加载图片

image - 在 MATLAB 中叠加两个图像

python/flask 构建错误与 url_for,额外的无

python - memcached 中对象的最佳序列化方法是什么?

python - 计算使用多个键找到字典值的次数

javascript - 根据 "alt"标签在输入时过滤图像

php - 是否有任何插件可以将缩略图等图像扩展到一些大尺寸?

c++ - 将代码从 C 转换为 C++

python - Pandas :返回 NaN 行