% *  This code was used in the following articles:
% *  [1] Learning 3-D Scene Structure from a Single Still Image, 
% *      Ashutosh Saxena, Min Sun, Andrew Y. Ng, 
% *      In ICCV workshop on 3D Representation for Recognition (3dRR-07), 2007.
% *      (best paper)
% *  [2] 3-D Reconstruction from Sparse Views using Monocular Vision, 
% *      Ashutosh Saxena, Min Sun, Andrew Y. Ng, 
% *      In ICCV workshop on Virtual Representations and Modeling 
% *      of Large-scale environments (VRML), 2007. 
% *  [3] 3-D Depth Reconstruction from a Single Still Image, 
% *      Ashutosh Saxena, Sung H. Chung, Andrew Y. Ng. 
% *      International Journal of Computer Vision (IJCV), Aug 2007. 
% *  [6] Learning Depth from Single Monocular Images, 
% *      Ashutosh Saxena, Sung H. Chung, Andrew Y. Ng. 
% *      In Neural Information Processing Systems (NIPS) 18, 2005.
% *
% *  These articles are available at:
% *  http://make3d.stanford.edu/publications
% * 
% *  We request that you cite the papers [1], [3] and [6] in any of
% *  your reports that uses this code. 
% *  Further, if you use the code in image3dstiching/ (multiple image version),
% *  then please cite [2].
% *  
% *  If you use the code in third_party/, then PLEASE CITE and follow the
% *  LICENSE OF THE CORRESPONDING THIRD PARTY CODE.
% *
% *  Finally, this code is for non-commercial use only.  For further 
% *  information and to obtain a copy of the license, see 
% *
% *  http://make3d.stanford.edu/publications/code
% *
% *  Also, the software distributed under the License is distributed on an 
% * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
% *  express or implied.   See the License for the specific language governing 
% *  permissions and limitations under the License.
% *
% */
function [ X, Y, Scale, Coeff, Coeffs ] = FindTarget( defaultPara, Field, Target, Field_top, Field_left, target_center_topOffset, target_center_leftOffset, ...
		NormalizedEpipoalLine, ImgScale, ScaleFactors, TargetFullyInField, EnableEpipolarLineFlag)

% [ X, Y, Scale, Coeff, Coeffs ] = FindTarget( Field, Target, Field_top, Field_left, NormalizedEpipoalLine, ...
%		ImgScale, ScaleFactors, TargetFullyInField, EnableEpipolarLineFlag)

% Search for Target image in Field image (gray) at multiple different
% Target sizes (scale factors).
% Field         - Image being searched
% Target        - Image being Sought
% ScaleFactors  - Vector of scale factors for Target, target is scaled
%   by each of these factors (linear ie # lines in target =
%   old_target_lies * ScaleFactor)
% TargetFullyInField - Set to True if you are CERTAIN that the Target
%   is fully in the Field. Helps ignore spurrious correlations, but
%   will prevent finding location of Target that is only partially in
%   Field. True Should be faster, but isn't appreciably.. sigh....

%    local_field     = histeq(Field); % should not to histogram equalization in such a small region

    EpipolarThre = 0.05;% used 0.05
    num_scales  = size( ScaleFactors, 2 );
    best_max     = 0.0;
	best_id = [];
	Coeffs = [];
	
    for scale_id = 1:num_scales
        current_scale   = ScaleFactors( scale_id );
        target_tmp      = imresize(Target, current_scale, 'bicubic');
%	disp('Scaling the target accordingly');
	top     = size(target_tmp,1);
	left    = size(target_tmp,2);
    	target_tmp_center_topOffset = target_center_topOffset*current_scale;
	target_tmp_center_leftOffset = target_center_leftOffset*current_scale;
        adj_row         = size(target_tmp, 1 ) - 1;
        adj_col         = size(target_tmp, 2 ) - 1;
        
	% Note normxcorr2 barfs if Target > Field, so skip iteration if
        %   target is scaled too big.
        if ( (size(target_tmp, 1 ) <= size(Field,1)) && (size(target_tmp, 2 ) <= size(Field,2)) ) % Field is always bigger than Target

            % This is where the Heavy lifting is done. Find norimalzied
            %   covaraince at all offsets between target and field
            %   (including partial overlaps)
	    if defaultPara.Flag.UseNormXCorr2 == 1
            	res             = normxcorr2( target_tmp, Field );     
	    elseif defaultPara.Flag.UseNormXCorr2 == 0
            	res             = xcorr2( target_tmp, Field );  
	    elseif defaultPara.Flag.UseNormXCorr2 == 2
            	res             = normxcorr2_mex( target_tmp, Field );     
	    end

            % When we KNOW the target is completely within the field, trim
            %   correlations that incldue partial overlaps, this reduces
            %   false positives.
            if (TargetFullyInField) 
                % If we know that the target is compeltely within the field,
                %   exclude portions of the correlation that are generated by
                %   only a partial overlap of the target and  field.
                height  = size(Field,1) - size(target_tmp,1) + 1;
                width   = size(Field,2) - size(target_tmp,2) + 1;
	    	clear target_tmp;
                % use only those results where the Target is compeltely
                %   inside the Field.
                res     = res( top:(top+height-1), left:(left+width-1) );
                adj_row  = 0;
                adj_col  = 0;
            end

            if EnableEpipolarLineFlag
                Xim = [ Field_left + reshape(repmat( 1:size(res,2), size(res,1),1) ,1, []) - adj_col;...
                    Field_top + reshape(repmat( 1:size(res,1)', 1, size(res,2)) ,1, []) - adj_row];
                Residual = abs( NormalizedEpipoalLine' *  [ Xim(1:2,:); ones(1, size(Xim(1:2,:),2))]);
                Mask = Residual <= EpipolarThre*max(ImgScale);	
                res( ~reshape(Mask, size(res,1), [])) = 0; % set to the lowest possible corrolation value
            end
            % Max(matrix) returns the largest value in each col, in a row vector
%            [ max_vals, max_row_inds ] = max( abs( res ) );
            % Find the Col with the bigest Max
%            [ max_val , max_col_ind  ] = max( max_vals );
            % Get the row & col with the largest correlation
%            max_row_ind = max_row_inds( max_col_ind );
            % Adjust to get offset of scaled Target, in field, in units of
            %   FIELD pixels.
	    if all(res == 0)
%                disp('Res is all not close enough to Epipolar line');
		continue;
	    end
% 		disp('Size of Res =');
% 		size(res)
	    [xymax,smax,xymin,smin] = extrema2(abs(res));
	    [ Vsort Isort]= sort(xymax,'descend');
	    
            if size(Isort,1) >=2
	    	[row_ind col_ind] = ind2sub(size(res),smax(Isort(1:2)));
	    elseif size(Isort,1) == 0
		continue;
	    else
%		disp('No other Similiar Point');
	    	[row_ind col_ind] = ind2sub(size(res),smax(Isort(1)));
	    end		

            Coeffs( scale_id ).index        = scale_id;
            Coeffs( scale_id ).targetScale  = current_scale;
            Coeffs( scale_id ).offsetRow    = row_ind(1) - adj_row + target_tmp_center_topOffset;
            Coeffs( scale_id ).offsetCol    = col_ind(1) - adj_col + target_tmp_center_leftOffset;
            Coeffs( scale_id ).correlation  = Vsort(1);

            if size(Isort,1) >=2
            	Coeffs( scale_id ).SecondCorrelation  = Vsort(2);
	    else
%		disp('No other Similiar Point');
            	Coeffs( scale_id ).SecondCorrelation  = 0;
	    end
%            Coeffs( scale_id ).offsetRow    = max_row_ind - adj_row + target_tmp_center_topOffset;
%            Coeffs( scale_id ).offsetCol    = max_col_ind - adj_col + target_tmp_center_leftOffset;
%            Coeffs( scale_id ).correlation  = max_val;

            if (( scale_id==1) || (Vsort(1) > best_max) ) 
                best_max = Vsort(1);
                best_id = scale_id;
            end % check for new best location among different Scale

        end % make sure target <= Field

    end % loop over all scaled
    
    if ~isempty(best_id)
    	X       = Coeffs( best_id ).offsetCol;
    	Y       = Coeffs( best_id ).offsetRow;
    	Scale   = Coeffs( best_id ).targetScale;  
    	Coeff   = [ Coeffs( best_id ).correlation; Coeffs( best_id ).SecondCorrelation];
    else
    	X       = 0;
    	Y       = 0;
    	Scale   = 1;  
    	Coeff   = [0; 0];
    end

return  %end function
