├── README.md ├── Supplementary material.pdf ├── code ├── reflectSuppress.m ├── slider_demo.fig └── slider_demo.m ├── demos ├── demo_image.png ├── readme ├── slider demo.mov └── video dereflection demo.mp4 └── figures ├── BusPortrait.jpg ├── Child_Glass.jpg ├── Dog-In-Window.jpg ├── building.jpg ├── conference_room.jpg ├── hotel.jpg ├── mall.jpg ├── office.jpg ├── outside_the_bus.jpg ├── outside_the_bus_2.jpg ├── snow.jpg ├── toy_example.jpg ├── train.jpg ├── train2.jpg ├── tree.jpg └── woman.jpg /README.md: -------------------------------------------------------------------------------- 1 | # reflectSuppress 2 | MATLAB implementation of the algorithm in the CVPR 2019 paper "**Fast Single Image Reflection Suppression via Convex Optimization**" https://arxiv.org/abs/1903.03889 3 | 4 | ## Image Demo 5 | ![alt text](https://github.com/yyhz76/reflectSuppress/blob/master/demos/demo_image.png) 6 | 7 | ## Video Demo 8 | https://youtu.be/7B1nibwNS4E 9 | 10 | ## Slider Demo 11 | https://youtu.be/wyRwZrot53U 12 | 13 | -------------------------------------------------------------------------------- /Supplementary material.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/Supplementary material.pdf -------------------------------------------------------------------------------- /code/reflectSuppress.m: -------------------------------------------------------------------------------- 1 | % single image reflection suppression via gradient thresholding and solving 2 | % PDE using discrete cosine transform(DCT) 3 | 4 | % Input: 5 | % Im - the input image 6 | % h - the gradient thresholding parameter 7 | % epsilon - the epsilon in Eq.(3) in the paper 8 | 9 | % Output: 10 | % T - the dereflected image 11 | 12 | 13 | % Sample run: 14 | 15 | % Im = imread('./figures/train2.jpg'); 16 | % T = reflectSuppress(Im, 0.033, 1e-8); 17 | % subplot(1,2,1); imshow(Im); subplot(1,2,2); imshow(T); 18 | 19 | 20 | function T = reflectSuppress(Im, h, epsilon) % move epsilon out of inputs 21 | 22 | Y = im2double(Im); 23 | [m, n, r] = size(Y); 24 | T = zeros(m,n,r); 25 | Y_Laplacian_2 = zeros(m,n,r); 26 | 27 | for dim = 1:r 28 | GRAD = grad(Y(:,:,dim)); 29 | GRAD_x = GRAD(:,:,1); 30 | GRAD_y = GRAD(:,:,2); 31 | GRAD_norm = sqrt(GRAD_x.^2 + GRAD_y.^2); 32 | GRAD_norm_thresh = wthresh(GRAD_norm, 'h', h); % gradient thresholding 33 | ind = (GRAD_norm_thresh == 0); 34 | GRAD_x(ind) = 0; 35 | GRAD_y(ind) = 0; 36 | GRAD_thresh(:,:,1) = GRAD_x; 37 | GRAD_thresh(:,:,2) = GRAD_y; 38 | Y_Laplacian_2(:,:,dim) = div(grad(div( GRAD_thresh))); % compute L(div(delta_h(Y))) 39 | end 40 | 41 | rhs = Y_Laplacian_2 + epsilon * Y; 42 | 43 | for dim = 1:r 44 | T(:,:,dim) = PoissonDCT_variant(rhs(:,:,dim), 1, 0, epsilon); % solve the PDE using DCT 45 | end 46 | 47 | end 48 | 49 | 50 | 51 | 52 | % solve the equation (mu*L^2 - lambda*L + epsilon)*u = rhs via DCT 53 | % where L means Laplacian operator 54 | function u = PoissonDCT_variant(rhs, mu, lambda, epsilon) 55 | 56 | [M,N]=size(rhs); 57 | 58 | k=1:M; 59 | l=1:N; 60 | k=k'; 61 | eN=ones(1,N); 62 | eM=ones(M,1); 63 | k=cos(pi/M*(k-1)); 64 | l=cos(pi/N*(l-1)); 65 | k=kron(k,eN); 66 | l=kron(eM,l); 67 | 68 | kappa=2*(k+l-2); 69 | const = mu * kappa.^2 - lambda * kappa + epsilon; 70 | u=dct2(rhs); 71 | u=u./const; 72 | u=idct2(u); % refer to Theorem 1 in the paper 73 | 74 | return 75 | end 76 | 77 | 78 | 79 | % compute the gradient of a 2D image array 80 | 81 | function B=grad(A) 82 | 83 | [m,n]=size(A); 84 | B=zeros(m,n,2); 85 | 86 | Ar=zeros(m,n); 87 | Ar(:,1:n-1)=A(:,2:n); 88 | Ar(:,n)=A(:,n); 89 | 90 | 91 | Au=zeros(m,n); 92 | Au(1:m-1,:)=A(2:m,:); 93 | Au(m,:)=A(m,:); 94 | 95 | B(:,:,1)=Ar-A; 96 | B(:,:,2)=Au-A; 97 | 98 | end 99 | 100 | 101 | % compute the divergence of gradient 102 | % Input A is a matrix of size m*n*2 103 | % A(:,:,1) is the derivative along the x direction 104 | % A(:,:,2) is the derivative along the y direction 105 | 106 | function B=div(A) 107 | 108 | [m,n,~]=size(A); 109 | B=zeros(m,n); 110 | 111 | T=A(:,:,1); 112 | T1=zeros(m,n); 113 | T1(:,2:n)=T(:,1:n-1); 114 | 115 | B=B+T-T1; 116 | 117 | T=A(:,:,2); 118 | T1=zeros(m,n); 119 | T1(2:m,:)=T(1:m-1,:); 120 | 121 | B=B+T-T1; 122 | end -------------------------------------------------------------------------------- /code/slider_demo.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/code/slider_demo.fig -------------------------------------------------------------------------------- /code/slider_demo.m: -------------------------------------------------------------------------------- 1 | % SLIDER_DEMO MATLAB code for single image reflection suppression 2 | 3 | function varargout = slider_demo(varargin) 4 | % SLIDER_DEMO MATLAB code for slider_demo.fig 5 | % SLIDER_DEMO, by itself, creates a new SLIDER_DEMO or raises the existing 6 | % singleton*. 7 | % 8 | % H = SLIDER_DEMO returns the handle to a new SLIDER_DEMO or the handle to 9 | % the existing singleton*. 10 | % 11 | % SLIDER_DEMO('CALLBACK',hObject,eventData,handles,...) calls the local 12 | % function named CALLBACK in SLIDER_DEMO.M with the given input arguments. 13 | % 14 | % SLIDER_DEMO('Property','Value',...) creates a new SLIDER_DEMO or raises the 15 | % existing singleton*. Starting from the left, property value pairs are 16 | % applied to the GUI before slider_demo_OpeningFcn gets called. An 17 | % unrecognized property name or invalid value makes property application 18 | % stop. All inputs are passed to slider_demo_OpeningFcn via varargin. 19 | % 20 | % *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one 21 | % instance to run (singleton)". 22 | % 23 | % See also: GUIDE, GUIDATA, GUIHANDLES 24 | 25 | % Edit the above text to modify the response to help slider_demo 26 | 27 | % Last Modified by GUIDE v2.5 11-Mar-2018 21:49:05 28 | 29 | % Begin initialization code - DO NOT EDIT 30 | 31 | addpath(genpath(pwd)) 32 | 33 | gui_Singleton = 1; 34 | gui_State = struct('gui_Name', mfilename, ... 35 | 'gui_Singleton', gui_Singleton, ... 36 | 'gui_OpeningFcn', @slider_demo_OpeningFcn, ... 37 | 'gui_OutputFcn', @slider_demo_OutputFcn, ... 38 | 'gui_LayoutFcn', [] , ... 39 | 'gui_Callback', []); 40 | if nargin && ischar(varargin{1}) 41 | gui_State.gui_Callback = str2func(varargin{1}); 42 | end 43 | 44 | if nargout 45 | [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); 46 | else 47 | gui_mainfcn(gui_State, varargin{:}); 48 | end 49 | % End initialization code - DO NOT EDIT 50 | 51 | 52 | % --- Executes just before slider_demo is made visible. 53 | function slider_demo_OpeningFcn(hObject, eventdata, handles, varargin) 54 | % This function has no output args, see OutputFcn. 55 | % hObject handle to figure 56 | % eventdata reserved - to be defined in a future version of MATLAB 57 | % handles structure with handles and user data (see GUIDATA) 58 | % varargin command line arguments to slider_demo (see VARARGIN) 59 | 60 | % Choose default command line output for slider_demo 61 | handles.output = hObject; 62 | 63 | 64 | % Update handles structure 65 | guidata(hObject, handles); 66 | 67 | % UIWAIT makes slider_demo wait for user response (see UIRESUME) 68 | % uiwait(handles.figure1); 69 | 70 | 71 | % --- Outputs from this function are returned to the command line. 72 | function varargout = slider_demo_OutputFcn(hObject, eventdata, handles) 73 | % varargout cell array for returning output args (see VARARGOUT); 74 | % hObject handle to figure 75 | % eventdata reserved - to be defined in a future version of MATLAB 76 | % handles structure with handles and user data (see GUIDATA) 77 | 78 | % Get default command line output from handles structure 79 | varargout{1} = handles.output; 80 | 81 | 82 | % --- Executes on slider movement. 83 | function slider1_Callback(hObject, eventdata, handles) 84 | % hObject handle to slider1 (see GCBO) 85 | % eventdata reserved - to be defined in a future version of MATLAB 86 | % handles structure with handles and user data (see GUIDATA) 87 | 88 | % Hints: get(hObject,'Value') returns position of slider 89 | % get(hObject,'Min') and get(hObject,'Max') to determine range of slider 90 | a = handles.a; 91 | 92 | h = get(hObject,'Value'); 93 | 94 | c = reflectSuppress(a, h, 1e-8); 95 | 96 | str = ['Threshold h:', ' ', sprintf('%.3f',h)]; 97 | 98 | set(handles.edit1, 'String', str); 99 | 100 | axes(handles.axes2); 101 | 102 | imshow(c); 103 | 104 | % --- Executes during object creation, after setting all properties. 105 | function slider1_CreateFcn(hObject, eventdata, handles) 106 | % hObject handle to slider1 (see GCBO) 107 | % eventdata reserved - to be defined in a future version of MATLAB 108 | % handles empty - handles not created until after all CreateFcns called 109 | 110 | % Hint: slider controls usually have a light gray background. 111 | if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) 112 | set(hObject,'BackgroundColor',[.9 .9 .9]); 113 | end 114 | 115 | 116 | % --- Executes on button press in Browse. 117 | function Browse_Callback(hObject, eventdata, handles) 118 | % hObject handle to Browse (see GCBO) 119 | % eventdata reserved - to be defined in a future version of MATLAB 120 | % handles structure with handles and user data (see GUIDATA) 121 | 122 | [filename, pathname] = uigetfile('*.jpg', 'Pick an image', '.\figures'); 123 | if isequal(filename,0) || isequal(pathname,0) 124 | disp('User pressed cancel') 125 | else 126 | a = imread(filename); 127 | 128 | axes(handles.axes1); 129 | imshow(a); 130 | handles.a = a; 131 | end 132 | % Update handles structure 133 | guidata(hObject, handles); 134 | 135 | 136 | 137 | function edit1_Callback(hObject, eventdata, handles) 138 | % hObject handle to edit1 (see GCBO) 139 | % eventdata reserved - to be defined in a future version of MATLAB 140 | % handles structure with handles and user data (see GUIDATA) 141 | 142 | % Hints: get(hObject,'String') returns contents of edit1 as text 143 | % str2double(get(hObject,'String')) returns contents of edit1 as a double 144 | 145 | 146 | % --- Executes during object creation, after setting all properties. 147 | function edit1_CreateFcn(hObject, eventdata, handles) 148 | % hObject handle to edit1 (see GCBO) 149 | % eventdata reserved - to be defined in a future version of MATLAB 150 | % handles empty - handles not created until after all CreateFcns called 151 | 152 | % Hint: edit controls usually have a white background on Windows. 153 | % See ISPC and COMPUTER. 154 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) 155 | set(hObject,'BackgroundColor','white'); 156 | end 157 | -------------------------------------------------------------------------------- /demos/demo_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/demos/demo_image.png -------------------------------------------------------------------------------- /demos/readme: -------------------------------------------------------------------------------- 1 | 2 | (i) The slider demo in the paper 3 | (ii) An HD video reflection suppression demo using the proposed algorithm 4 | -------------------------------------------------------------------------------- /demos/slider demo.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/demos/slider demo.mov -------------------------------------------------------------------------------- /demos/video dereflection demo.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/demos/video dereflection demo.mp4 -------------------------------------------------------------------------------- /figures/BusPortrait.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/figures/BusPortrait.jpg -------------------------------------------------------------------------------- /figures/Child_Glass.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/figures/Child_Glass.jpg -------------------------------------------------------------------------------- /figures/Dog-In-Window.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/figures/Dog-In-Window.jpg -------------------------------------------------------------------------------- /figures/building.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/figures/building.jpg -------------------------------------------------------------------------------- /figures/conference_room.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/figures/conference_room.jpg -------------------------------------------------------------------------------- /figures/hotel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/figures/hotel.jpg -------------------------------------------------------------------------------- /figures/mall.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/figures/mall.jpg -------------------------------------------------------------------------------- /figures/office.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/figures/office.jpg -------------------------------------------------------------------------------- /figures/outside_the_bus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/figures/outside_the_bus.jpg -------------------------------------------------------------------------------- /figures/outside_the_bus_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/figures/outside_the_bus_2.jpg -------------------------------------------------------------------------------- /figures/snow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/figures/snow.jpg -------------------------------------------------------------------------------- /figures/toy_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/figures/toy_example.jpg -------------------------------------------------------------------------------- /figures/train.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/figures/train.jpg -------------------------------------------------------------------------------- /figures/train2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/figures/train2.jpg -------------------------------------------------------------------------------- /figures/tree.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/figures/tree.jpg -------------------------------------------------------------------------------- /figures/woman.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyhz76/reflectSuppress/5a693a2d1ccf7d2b2f991dc4c81c41ece9077aaa/figures/woman.jpg --------------------------------------------------------------------------------