Refactoring the findMultiColorMarker function
Refactoring the findMultiColorMarker function
I propose refactoring the findMultiColorMarker
function for enhanced readability and to enable other functions (see shoulder detection) to use parts of it, especially the color blob detection.
Structure
Let's first try to get an Overview over the current structure of findMultiColorMarker first
. As far as I can tell (please correct me, when I'm wrong), the currrent structure is something like this:
graph TD;
take(Take next colormap);
colorParams(create the HSV thresholding parameters);
mid(calculate mid hue);
thresh(threshold);
morph(open/close binary mask);
cont(find contours);
take2(take the next contour);
rect(find bounding rect of contour);
ratio(check ratio);
area(check area);
edge(check if at edge);
col(pick color for this head);
take --> colorParams;
subgraph colorBlobDetection
colorParams --> mid;
mid --> thresh;
thresh --> morph;
morph --> cont;
cont --> take2;
take2 --> rect;
rect --> ratio;
ratio --> area;
ratio --too big--> take2;
area --> edge;
area -- too big or small --> take2;
edge --> col;
edge -- at edge --> take2;
end
method{Which method is used?};
col --> method;
black(With black dot);
method -- use BlackDot --> black;
black --> take2;
method -- withCode --> code(With Aruco Marker);
code --> take2;
method -- none --> add(Add point);
add --> take2;
graph TD;
blackCrop(create Crop Rect);
posit(Restrict position*);
blackSubImg(take subImg from cropRect);
colCov(custom color conversion with midHue);
thresh2(threshold);
findContour(find countours);
check(check if contour has acceptable area and ratio);
darkest(determine darkest point in accepted contour);
addBlack(Add point, if darkest point is dark enough);
subgraph blackDot
blackCrop --> posit;
posit --> blackSubImg;
blackSubImg --> colCov;
colCov --> thresh2;
thresh2 --> findContour;
findContour --> check;
check --> darkest;
darkest --> addBlack;
end
graph TD
subgraph withCode
crop(create crop rect) --> subImg(create subImg from cropRect);
subImg --> findCode(find code marker in subImg);
findCode --> add(Depending of if the code was found an if it is mandatory, add it to cross list and update its color);
end
Proposal
I already marked three areas which do their very own job and I'd propose making them into their own functions. Especially the colorBlobDetection, as it could be reused by the shoulder markers.
When doing that, we would change the structure of the code. We would first generate a vector of contours which suffice as color blobs and then refine this vector, if we use a special method(blackDot, Aruco). So we'd have 2 loops instead of 1. The alternative would be having two different functions for detecting blobs and filtering out blobs which are too big/small/thin/... then we could have the filtering function as part of our single loop.
So the two ways are:
graph TD
findColorBlobs --> method(special method) --> Add
graph TD
findColorBlobContours --> t[take contour]
t --> filterContour --> method(special method) --> Add;
Add --> t;
Of course one could make even more fine grained functions and I would say that e.g. the restrict position part of the black dot method can be in its own function. Also some things might get shuffled up (midHue is only used for the black dot, so maybe move that at least in the corresponding if-branch). But this is the bare minimum for readability and usablility. Everything after that is the cherry on top.
So I think it would make the code more readable and reusable when splitting it up like this. I personally don't have a favorite under the last two options.