<?xml version="1.0" encoding="UTF-8"?>
<hdevelop file_version="1.1" halcon_version="13.0">
<procedure name="estimate_best_rectangle_overlap">
<interface>
<io>
<par name="RegionSeg" base_type="iconic" dimension="0"/>
</io>
<oo>
<par name="Rectangle" base_type="iconic" dimension="0"/>
</oo>
<ic>
<par name="Rotation" base_type="ctrl" dimension="0"/>
<par name="Scale" base_type="ctrl" dimension="0"/>
<par name="OptimizationMethod" base_type="ctrl" dimension="0"/>
<par name="initial_box_coordinate" base_type="ctrl" dimension="0"/>
</ic>
<oc>
<par name="initial_box_coordinates" base_type="ctrl" dimension="0"/>
<par name="best_overlap" base_type="ctrl" dimension="0"/>
<par name="best_box_coordinate" base_type="ctrl" dimension="0"/>
</oc>
</interface>
<body>
<c> * Copyright (c) MVTec Software GmbH.  All rights reserved.</c>
<c> *</c>
<c> * All use of this software is subject to the terms of the revised BSD</c>
<c> * license.  You should have received a copy of this license along</c>
<c> * with this source code in a file named "license.txt."</c>
<c></c>
<c>* This routine tries to find the best rectangle for a given segmentation.</c>
<c>* (1) If no initial value is passed some reasonable ones are generated.</c>
<c>* (2) The single initial values are optimized </c>
<c>* (3) The resulting local optmias are compared. If they are too different</c>
<c>* further initial values are sampled between the locally optimal parameters</c>
<c>* and the resulting best rectangle choosen.</c>
<c></c>
<c>* Border treatment: do not clip regions!</c>
<l>get_system ('clip_region',ClipRegion)</l>
<l>set_system ('clip_region','false')</l>
<c></c>
<c>* The maximal difference the optimas may have</c>
<l>MaxDiff := 0.01</l>
<c>* If the optimas are more different than MaxDiff, we sample NumRandSamples </c>
<c>* to ensure we're optimal</c>
<l>NumRandSamples := 50</l>
<c>* The Offset is used to wobble around the maxima to ensure it's stable</c>
<c>* (and it's used to extend the search area when the maximas are different)</c>
<l>NumWobble := 10</l>
<l>Offset := [10,10,0,0,0]</l>
<l>if (Scale)</l>
<l>    Offset := Offset + [0,0,10,10,0]</l>
<l>endif</l>
<l>if (Rotation)</l>
<l>    Offset := Offset + [0,0,0,0,10]</l>
<l>endif</l>
<c>* For now we have a flag which either adds the passed initial value to the set of</c>
<c>* initial values or just uses the initial value</c>
<l>AddInitialValues := true</l>
<c>*</c>
<c>* If DEBUG is true the intermediate optimization steps of improving the maxima are</c>
<c>* displayed to help see whats going on</c>
<l>DEBUG := false</l>
<c></c>
<l>if (DEBUG)</l>
<l>    dev_open_window (0, 0, 512, 512, 'black', WindowHandle)</l>
<l>endif</l>
<c>*****************************************************</c>
<c>* (1) Generate initial candidates if none is passed</c>
<c>*****************************************************</c>
<l>if (initial_box_coordinate # [] and Scale == false and Rotation == false)</l>
<l>    initial_box_coordinates := initial_box_coordinate</l>
<l>    InitialRectangles := 'initial box coordinates'</l>
<l>elseif (initial_box_coordinate == [] or AddInitialValues)</l>
<l>    if (Rotation)</l>
<l>        InitialRectangles := ['rectangle1','rectangularity','rectangle2','inner_circle','inner_rectangle1']</l>
<l>    else</l>
<l>        InitialRectangles := ['rectangle1','inner_circle','inner_rectangle1']</l>
<l>    endif</l>
<l>    initial_rectangles (RegionSeg, Rectangles, InitialRectangles, overlap_bb_initial, initial_box_coordinates)</l>
<l>    if (AddInitialValues and initial_box_coordinate # [])</l>
<l>        initial_box_coordinates := [initial_box_coordinates,initial_box_coordinate]</l>
<l>        InitialRectangles := [InitialRectangles,'initial box coordinates']</l>
<l>    endif</l>
<l>endif</l>
<c>*</c>
<c>****************************************</c>
<c>* (2) Optimize the initial candidates</c>
<c>***************************************</c>
<c>* Loop over the different initial values</c>
<l>best_box_coordinates := []</l>
<l>best_overlaps := []</l>
<l>for Index := 1 to |InitialRectangles| by 1</l>
<l>    initial_box_coordinate := initial_box_coordinates[(5*(Index-1)):(5*Index-1)]</l>
<l>    optimize_rectangle_overlap (RegionSeg, Rectangle, initial_box_coordinate, Rotation, Scale, OptimizationMethod, false, [], best_overlap, best_box_coordinate)</l>
<l>    best_box_coordinates := [best_box_coordinates, best_box_coordinate]</l>
<l>    best_overlaps := [best_overlaps,best_overlap]</l>
<l>endfor</l>
<c></c>
<c>********************************************************************</c>
<c>* (3) Find the best rectangle from the different local minimas....</c>
<c>********************************************************************</c>
<l>if (OptimizationMethod # 'exhaustive')</l>
<c>    * Find the optimal region given the different optimal candidates</c>
<l>    if (DEBUG)</l>
<l>        gen_empty_obj (BestRectangles)</l>
<l>        for Index := 1 to |best_box_coordinates|/5 by 1</l>
<l>            best_box_coordinate := best_box_coordinates[(5*(Index-1)):(5*Index-1)]</l>
<l>            gen_rectangle_b (Rectangle0, best_box_coordinate)</l>
<l>            concat_obj (BestRectangles, Rectangle0, BestRectangles)</l>
<l>        endfor</l>
<l>    endif</l>
<c>    *</c>
<c>    * best</c>
<l>    best_box_coordinate := best_box_coordinates[5*(find(best_overlaps,max(best_overlaps))[0]):(5*(find(best_overlaps,max(best_overlaps))[0]+1)-1)]</l>
<l>    best_overlap := max(best_overlaps)</l>
<l>    gen_rectangle_b (Rectangle, best_box_coordinate)</l>
<c>    *</c>
<c>    * Check if the overlaps are significantly different</c>
<l>    if (sum(abs(best_overlaps-max(best_overlaps)))&gt;MaxDiff)</l>
<c>        * ToDo: We currently randomly search for better candidates on a grid</c>
<c>        *       between the minimal and maximal parameter values. What else could we do?</c>
<l>        if (DEBUG)</l>
<c>            * If DEBUG is true, display the different candidates and their overlap</c>
<l>            count_obj (BestRectangles, Number)</l>
<l>            dev_clear_window ()</l>
<l>            select_obj (BestRectangles, ObjectSelected, 1)</l>
<l>            disp_region_alpha (ObjectSelected, '#ff0000', 50)</l>
<l>            disp_message (WindowHandle, 'Overlap: ' + best_overlaps[0], 'window', 12, 12, '#ff0000', 'true')</l>
<l>            if (Number &gt; 1)</l>
<l>                select_obj (BestRectangles, ObjectSelected, 2)</l>
<l>                disp_region_alpha (ObjectSelected, '#00ff00', 50)</l>
<l>                disp_message (WindowHandle, 'Overlap: ' + best_overlaps[1], 'window', 30, 12, '#00ff00', 'true')</l>
<l>            endif</l>
<l>            if (Number &gt; 2)</l>
<l>                select_obj (BestRectangles, ObjectSelected, 3)</l>
<l>                disp_region_alpha (ObjectSelected, '#0000ff', 50)</l>
<l>                disp_message (WindowHandle, 'Overlap: ' + best_overlaps[2], 'window', 48, 12, '#0000ff', 'true')</l>
<l>            endif</l>
<l>            dev_set_draw ('margin')</l>
<l>            dev_set_color ('white')</l>
<l>            dev_display (RegionSeg)</l>
<l>            stop()</l>
<l>        endif</l>
<c>        * First let's find out how many of the best rectangles are significantly different</c>
<l>        diffs := sum(abs(best_overlaps-max(best_overlaps))[&gt;]MaxDiff)</l>
<l>        num_initial := |best_overlaps|</l>
<c>        * We compute a slightly extended parameter range where we expect</c>
<l>        box_coordinate_min := best_box_coordinates[5*(find(best_overlaps,min(best_overlaps))[0]):(5*(find(best_overlaps,min(best_overlaps))[0]+1)-1)]</l>
<l>        box_coordinate_max := best_box_coordinates[5*(find(best_overlaps,max(best_overlaps))[0]):(5*(find(best_overlaps,max(best_overlaps))[0]+1)-1)]</l>
<c>        * For the angle we might need to take more care. To make sure we don't sample too widely,</c>
<c>        * normalize the angles of both boxes</c>
<l>        consolidate_box_coordiniates (box_coordinate_min, box_coordinate_min)</l>
<l>        consolidate_box_coordiniates (box_coordinate_max, box_coordinate_max)</l>
<c>        * We sort b_lower and b_upper to actually be a lower and upper bound for the parameters</c>
<l>        box_coordinate_lower := (box_coordinate_min [&lt;] box_coordinate_max)*box_coordinate_min + (box_coordinate_min [&gt;=] box_coordinate_max)*box_coordinate_max</l>
<l>        box_coordinate_upper := (box_coordinate_min [&gt;] box_coordinate_max)*box_coordinate_min + (box_coordinate_min [&lt;=] box_coordinate_max)*box_coordinate_max</l>
<c>        * Extend the sampling box slgihtly to increase the variations</c>
<l>        box_coordinate_lower := box_coordinate_lower-Offset</l>
<l>        box_coordinate_upper := box_coordinate_upper+Offset</l>
<c>        * We need to ensure that box_coordinate_lower is within bounds</c>
<l>        box_coordinate_lower[2:3] := [box_coordinate_lower[2:3][&lt;]1.0]*1.0 + [box_coordinate_lower[2:3][&gt;=]1.0]*box_coordinate_lower[2:3]</l>
<l>        box_coordinate_lower[2:3] := [box_coordinate_lower[2:3][&lt;]1.0]*1.0 + [box_coordinate_lower[2:3][&gt;=]1.0]*box_coordinate_lower[2:3]</l>
<c>        * We sample NumRandSamples parameters between the minimal and maximal values</c>
<l>        for Index := 1 to NumRandSamples by 1</l>
<l>            box_coordinate_test := box_coordinate_lower+rand(5)*abs(box_coordinate_lower-box_coordinate_upper)</l>
<l>            optimize_rectangle_overlap (RegionSeg, RectangleTest, box_coordinate_test, Rotation, Scale, OptimizationMethod, false, [], tmp_overlap, tmp_box_coordinate)</l>
<l>            if (DEBUG)</l>
<l>                dev_clear_window ()</l>
<c>                * Display the current best, the initial value and the best_value</c>
<l>                gen_rectangle_b (InitialRectangle, box_coordinate_test)</l>
<l>                disp_region_alpha (InitialRectangle, '#ff55ff', 20)</l>
<l>                disp_region_alpha (RectangleTest, '#ffff00', 90)</l>
<l>                disp_message (WindowHandle, 'Test overlap: ' + tmp_overlap, 'window', 12, 12, '#ff9920', 'true')</l>
<l>                disp_region_alpha (Rectangle, '#00ff00', 50)</l>
<l>                disp_message (WindowHandle, 'Best overlap: ' + best_overlap, 'window', 30, 12, '#00ff00', 'true')</l>
<l>                dev_set_draw ('margin')</l>
<l>                dev_set_color ('white')</l>
<l>                dev_display (RegionSeg)</l>
<l>                wait_seconds (0.1)</l>
<l>            endif</l>
<c>            * If there is a better candidate then yey! Lets keep it!</c>
<l>            if (tmp_overlap&gt;best_overlap)</l>
<l>                best_box_coordinate := tmp_box_coordinate</l>
<l>                best_overlap := tmp_overlap</l>
<l>                gen_rectangle_b (Rectangle, best_box_coordinate)</l>
<l>            endif</l>
<l>        endfor</l>
<l>    endif</l>
<c>    *</c>
<c>    * We whobble a bit around the now obtained maximum</c>
<l>    box_coordinate_lower := best_box_coordinate-Offset</l>
<l>    box_coordinate_upper := best_box_coordinate+Offset</l>
<c>    * We need to ensure that box_coordinate_lower is within bounds</c>
<l>    box_coordinate_lower[2:3] := [box_coordinate_lower[2:3][&lt;]1.0]*1.0 + [box_coordinate_lower[2:3][&gt;=]1.0]*box_coordinate_lower[2:3]</l>
<l>    box_coordinate_lower[2:3] := [box_coordinate_lower[2:3][&lt;]1.0]*1.0 + [box_coordinate_lower[2:3][&gt;=]1.0]*box_coordinate_lower[2:3]</l>
<c>    *</c>
<l>    for Index := 1 to NumWobble by 1</l>
<l>        box_coordinate_test := box_coordinate_lower+rand(5)*abs(box_coordinate_lower-box_coordinate_upper)</l>
<l>        optimize_rectangle_overlap (RegionSeg, RectangleTest, box_coordinate_test, Rotation, Scale, OptimizationMethod, false, [], tmp_overlap, tmp_box_coordinate)</l>
<l>        if (DEBUG)</l>
<l>            dev_clear_window ()</l>
<c>            * Display the current best, the initial value and the best_value</c>
<l>            gen_rectangle_b (InitialRectangle, box_coordinate_test)</l>
<l>            disp_region_alpha (InitialRectangle, '#ff55ff', 20)</l>
<l>            disp_region_alpha (RectangleTest, '#ffff00', 90)</l>
<l>            disp_message (WindowHandle, 'Test overlap: ' + tmp_overlap, 'window', 12, 12, '#ff9920', 'true')</l>
<l>            disp_region_alpha (Rectangle, '#00ff00', 50)</l>
<l>            disp_message (WindowHandle, 'Best overlap: ' + best_overlap, 'window', 30, 12, '#00ff00', 'true')</l>
<l>            dev_set_draw ('margin')</l>
<l>            dev_set_color ('white')</l>
<l>            dev_display (RegionSeg)</l>
<l>            wait_seconds (0.05)</l>
<l>        endif</l>
<c>         * If there is a better candidate then yey! Lets keep it!</c>
<l>        if (tmp_overlap&gt;best_overlap)</l>
<l>            best_box_coordinate := tmp_box_coordinate</l>
<l>            best_overlap := tmp_overlap</l>
<l>            gen_rectangle_b (Rectangle, best_box_coordinate)</l>
<l>        endif</l>
<l>    endfor</l>
<l>endif</l>
<c>*</c>
<l>if (DEBUG)</l>
<l>    dev_close_window ()</l>
<l>endif</l>
<c>*</c>
<l>set_system ('clip_region',ClipRegion)</l>
<c>*</c>
<l>return ()</l>
</body>
<docu id="estimate_best_rectangle_overlap">
<parameters>
<parameter id="OptimizationMethod"/>
<parameter id="Rectangle"/>
<parameter id="RegionSeg"/>
<parameter id="Rotation"/>
<parameter id="Scale"/>
<parameter id="best_box_coordinate"/>
<parameter id="best_overlap"/>
<parameter id="initial_box_coordinate"/>
<parameter id="initial_box_coordinates"/>
</parameters>
</docu>
</procedure>
</hdevelop>
