Удаление теней в Python OpenCV

Я пытаюсь реализовать удаление теней в python OpenCV, используя метод минимизации энтропии Финлейсона и др. др.:

«Внутренние образы с помощью минимизации энтропии», Финлейсон, и др. др.

Я не могу сопоставить результаты с бумагой. Мой график энтропии не совпадает с графиком из статьи, и я получаю неправильную минимальную энтропию.

Какие-нибудь мысли? (У меня гораздо больше исходного кода и документов по запросу)

#############
# 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()

Вывод:

Оригинал

rg Цветность

Журнал цветности

Среднегеометрические логарифмические цветности

Двумерные геометрические логарифмические цветности

Минимизация энтропии

«Приближение

Инвариантная цветность rg


person A. Hendry    schedule 11.12.2017    source источник
comment
Я получаю что-то подобное, но с бумагой тоже по-другому. i.stack.imgur.com/ZK0Zn.png   -  person Kinght 金    schedule 11.12.2017
comment
Разочарование, право! Как будто он почти готов, но чего-то все еще не хватает. Мне кажется, это очевидно, но я не знаю...   -  person A. Hendry    schedule 11.12.2017
comment
у кого-нибудь есть решение?   -  person A. Hendry    schedule 12.12.2017
comment
Здравствуйте, А. Хендри, у вас получилось? Я пытаюсь удалить тень от некоторых листьев, чтобы сегментировать ее.   -  person Tarcisiofl    schedule 25.06.2018
comment
Я заметил, что кто-то пытается сделать то же самое в python здесь, но они, похоже, остановились на том же шаге цветности, что и вы достигли выше. Две интересные статьи 2012 года: Shadow Detection: A Survey and Comparative Evaluation of Recent Methods, посвященные следующим методам. – на основе цветности, физической, геометрической, текстурной. Удаление теней для аэрофотоснимков с помощью теоретико-информационного внутреннего анализа изображения From 3 goo   -  person Rossoe    schedule 03.06.2019
comment
Удалось ли вам преобразовать изображение цветности обратно в RGB в конце?   -  person Daniel C Jacobs    schedule 26.02.2021


Ответы (1)


Удаление теней с использованием формирования изображения, инвариантного к освещению (Ранавира, Дрю) отмечает в разделе «Результаты и обсуждение», что результаты для изображений JPEG и изображений PNG отличаются из-за сжатия JPEG. Таким образом, ожидать результатов, точно таких же, как показано в «Внутренних изображениях путем минимизации энтропии» (Финлейсон и др.), Может быть неразумно.

Я также заметил, что вы не добавляете обратно «дополнительный свет», который автор рекомендует в других статьях.

Кроме того, при определении rg_chrom порядок каналов должен быть BGR вместо RGB, как вы использовали.

Я работаю над реализацией документа, поэтому ваш код был мне чрезвычайно полезен. Спасибо за это

person Shawn Mathew    schedule 19.02.2018
comment
У меня сейчас есть рабочая реализация. Я переписывался с авторами статьи. Есть явное желание не публиковать это на GitHub. Пожалуйста, не делайте этого, если собирались. - person A. Hendry; 21.02.2018
comment
Извините, получилось высокомерно, резко и совсем не так. Пожалуйста, позвольте мне объяснить. Большое спасибо, что посмотрели мой пост и мой код! В этом и смысл: делиться с миром, чтобы учиться и расти. Я тоже ценю ваши отзывы! Вы абсолютно правы. Сжатие JPEG с помощью FFT (или любого другого сжатия без потерь) удаляет жизненно важные данные из изображения, и вы не получите правильного результата. Дополнительный свет также важен, и вы должны быть осторожны с BGR и RGB. - person A. Hendry; 21.02.2018
comment
Причина, по которой я спросил, не будете ли вы публиковать сообщения на Github, заключается в том, что Dr.'s Finlayson, et. al., есть студенты, которые должны внедрить код как часть своей курсовой работы. Думаю, я собираюсь спросить еще раз, могу ли я отправить запрос на включение в OpenCV, чтобы добавить их алгоритм в библиотеку, обязательно отдав им должное. Я не верю, что есть что-то юридически запрещающее нам публиковать сообщения на GitHub, поскольку исходный код Python является открытым, но я просто делаю это из чести. Посмотрим, смогу ли я связаться с ними снова. Еще раз, @Shawn Mathew, большое спасибо и удачи! - person A. Hendry; 21.02.2018
comment
Вы случайно не делаете это для Udacity, другого курса или для личного назидания? - person A. Hendry; 21.02.2018
comment
@A.Hendry, спасибо, что сообщили мне. Я реализую это для проекта, над которым я работаю. Последние два дня я просматривал его документы, чтобы понять, как это реализовать. Хотелось бы, чтобы в документах было больше деталей реализации. Надеюсь, вы получили разрешение на добавление кода в репозиторий opencv. Это было бы невероятно ценно для многих людей, поскольку результаты, показанные в статье, просто фантастические. - person Shawn Mathew; 21.02.2018
comment
Не могу не согласиться. Я написал вчера вечером и до сих пор жду ответа. - person A. Hendry; 22.02.2018
comment
Возможно, студенты могли бы просто использовать систему чести, а не напрямую использовать функции OpenCV. Мы так делали, когда я учился в колледже. - person Shawn Mathew; 24.02.2018
comment
Возможно. Я тоже. Я так и не узнал ничего, если я все равно скопировал код ... Я до сих пор не получил от них ответа, поэтому я предполагаю, что на данный момент это все еще не работает. - person A. Hendry; 25.02.2018
comment
@A.Hendry, если вы можете поделиться своим решением, не могли бы вы связаться со мной через мой GH - github. com/GeorgeR - person George R; 18.03.2020