900731 Data Handling for Eye-in-the-Sea on MARS : Notes from Porting Segmentation Code from Matlab to C++ This page last changed on Jan 23, 2007 by kgomes. I am using the OpenCV libraries where I can so I had to build them and store them locally in my home directory on nanomia. After build them, I needed to include them in the LD_LIBRARY_PATH. So in order to run the test-segmentation program, I have to do the following (example for Baxter clips): cd originalppms/Baxter export LD_LIBRARY_PATH=/usr/lib/aved:/home/kgomes/opencv-install/lib ~/aved/mbarivision/test-segmentation --input-frames=500-501@0 --mbari-segment-algorithm=AdaptiveThreshold --mbari-segment-algorithm-se-type=Benthic baxter Now in order to view images, I had to export my display using: export DISPLAY=skagit.shore.mbari.org:0.0 and run a Xserver on skagit. Then I could view the results with: gm display baxter_segmented_000500.ppm 1/19/2007 I have the adapative thresholding working, but the results are quite different. I am going to try to examine the differences in each step of the process to see if I can minimize the differences. The first step in the Matlab code is to convert the raw image to greyscale calling rgb2gray, in the C++ code, is uses the method called luminance to convert it to grayscale. When I take a difference of the two images and look at a histogram, they are close, but there are some differences (in the list below the rest of the values were 0).
    0        1103
    1        2790
    2        7560
    3       30549
    4       86626
    5      104728
    6       70701
    7       19907
    8        1848
    9         448
    10        255
    11        164
    12        166
    13         76
    14         77
    15         53
    16         24
    17         22
    18         18
    19          4
    20          1
    21          0
So the starting point looks like the luminance and rgb2gray and not exactly the same, but maybe they are close enough. It the errors compound, I will come back to this. Oh, by the way, I also converted the image to an OpenCV image and back to make sure that conversion was not causing any errors. I got the exact same results, so the conversion seems to be fine. So now, I moved to the next step, which is the matlab imopen function using a structing element in the shape of a disk of radius 15. In OpenCV I constructed one of their structing elements and then ran the cvMorphologyEx function and compared that to the matlab opened image. Fortunately, not much changed and they looked very close, here is the histogram of the differences:
    0        1639
    1        4581
    2        9865
    3       36890
    4       89465
    5      108729
    6       62680
    7       12125
    8         590
    9         217
    10        193
    11         89
    12         27
    13         14
    14         10
    15          0
    16          0
    17          5
    18          0
Now the next step is to compare the images after subtracting the background from the original image. Here is the difference histogram:
    0       150603
    1       142764
    2        20474
    3         3754
    4         1887
    5         1542
    6         1124
    7         1005
    8          876
    9          835
    10         736
    11         432
    12         358
    13         235
    14         172
    15         109
    16          77
    17          50
    18          21
    19          25
    20          11
    21           8
    22           8
    23           4
    24           7
    25           0
    26           2
    27           1
    28           0
Although the images have diverged a little as the histogram spreads out, it actually is getting closer as the number move more towards zero. Now here is where it gets messy. OpenCV did not have a adaptive histogram equalization algorithm, so I took the one from the Graphic Gems IV code and tried to get it working here. There are a large number of variables to tweak so I am just playing with those variables to try to shrink the differences down (if that is possible). As a first pass, the results weren't horrible (leaving off bin numbers), but could be better. Let the iterations begin!
           23265
           53846
           26447
           64754
           28573
           25928
           25770
           29613
            9120
           12304
            7148
            4507
            3050
            2213
            1583
             909
             946
             825
             608
             434
             476
             465
             375
             312
             397
             342
             269
             275
             337
             258
             199
             163
             149
             149
             128
             121
              99
              95
              99
              79
              69
              58
              57
              58
              50
              48
              38
              33
              19
              12
               5
               4
               7
              11
               3
               4
               5
               2
               2
               2
               1
               0
               0
               1
               0
               0
               1
So after some iteration, it looks like an fClipLimit of 5.1 or 5.2 is the best for the test image. The only question I would have is whether or not this will change from image to image. I think, though because it is simply matrix manipulations, the most closely matched will always be the most closely matched. For now I will leave it at 5.1. If you are interested in how I found the best value, you can look at the excel spreadsheet I've attached (AdaptFClipLimitChart.xls). The next step is to compare them after converting it to a binary image. In matlab, the graythresh function is used to find the threshold value using Otsu's method. After this is found, then that is applied to threshold the image using im2bw. In the C++ code, I used the cvThreshold method and used an undocumented type called CV_THRESH_OTSU (found in a forum). The results were not that good. I had 15,000 pixels (out of 45,000) that were thresholded differently. I grabbed the value from the threshold matlab method and used that as the threshold (matlab generated a level of 0.2 which comes out to 51.2 that I used in the cvThreshold with type CV_THRESH_BINARY. The results were WAY better and only 3,000 pixles were different. Now, the level that cvThreshold calculates is done by a routine called icvGetThreshVal_Otsu() and there is no visibility to see what value that is calculating. A forum suggested cutting/pasting the open code into my code ... maybe I will try that ... Attachments: AdaptFClipLimitChart.xls (application/octet-stream)

Document generated by Confluence on Feb 03, 2026 14:51