Finding threshold for autocrop

I have grayscale images that I want to autocrop, but I do not know which threshold to use. Some images have a black border, some don’t. I was thinking of generating a histogram of the images. If there is a large spike for black dots, then I crop otherwise I don’t. If I want to crop, then I use the end of the large spike (so the lightest intensity still belonging to the black spike) as the threshold. So far my idea. Question: Is this valid? if it is, how can I implement this in KNIME, more specifically, how can I get the histogram?

Hi @M42,
you can get a histogram using the Feature Calculator node, via the Histogram Features Feature Set. This will give you a histogram in a KNIME table, with each column containing the intensity value for a bin.

You could use a lower resolution histogram (with a smaller number of bins), and a manual threshold to trigger this. See the attached workflow for an example:
Autocrop.knwf (117.4 KB)

I am not sure how you can detect this easily, how do you plan to define this “end of the spike”? You can probably get quite far with a manually set threshold, or do you have great variance in the “blackness” of the border in your images?.

best,
Gabriel

Hi @gab1one,
I am not quite sure how to approach the issue myself yet. I am mostly tinkering. I had noticed that the histograms differ from each other for the images using the Image Viewer node (red is just the background color):

First you see the histogram of an image of a passport - little text, mostly, an image, no border:

Here we see a spike for middle bright grays.

Next there is a scan of an text with a very small border:

Finally, we see the large black spike for a scan of text with a large black border:

My idea was to cut this of.

Important to notice here: My black borders are not completely black, just nearly black. Because of this I cannot say that the manual threshold of the Auto Crop should be just the very black pixels.

Another idea I got from reading some literature on the topic and then searching in the KNIME nodes, is to use the Global Thresholder node and then a Thresholding Method like Otsu. However, the node does not return the threshold that the Otsu method found.

So a solution might be: After using the Global Thresholder with Otsu, I use the Auto Crop node on the transformed image, append the cropped image to the table of the original image and then use the Image Calculator node to 1) put them on top (that part is kind of fuzzy, because the Auto Crop made a smaller image, so I don’t know how to align them properly) and 2) make everything black that was not in the cropped image. The image now as a true black border (not the sort-of-black-border as I had before). Now I can use the Auto Crop node with a very small manual threshold.

But as I wrote - i am here also fuzzy on the details, on how to align the two images again after the first Auto Crop of the “masking image”.

You should be able to do this, the cropper does not remove the relative position information of the cut out image, so you can use the GroupBy node with the aggregation method Compose Image. You will need to edit the parameters of that method to set the Interval to the original image size.
Feel free to ask if you have any more questions with this.
best,
Gabriel

@gab1one Thanks for the flow idea. I am stuck because at quite a few places, there is quite a bit of confusion regarding the pixel types. I openend a new thread for that and will come back, once I got that: List of Pixel types (e.g. for Image Converter node)

Additionally I would need to know: What does Compose Image do? Is it multiplying the pixel values or adding them up? How does it handle different pixel types? (…and where is that documented if it already is?)

@gab1one So, I got the work flow running correctly, after the pixel type issue has been resolved. However, my previous question has not been answered: What does the Compose Image aggregation do exactly?

The result is certainly not cropped or anything like that. I set the Interval to the either image (the cropped and the not cropped) and it did not work.

I attach a workflow: Autocropping of Images.knwf (25.4 KB)

Edit: I understand now, what the problem is: I need to set all the values of the cropped images to 0.0 and say to the GroupBy node that 0.0 is the background. I can set the pixels to 0.0 with the Image Calculator node, but the Image Calculator node deletes the offset. Using the Advanced Settings’ should help, but it does not. Maybe that is a bug - I am not sure. I can extract the offset values with the Image Properties node, but I have no way of putting them back into the image.

Honestly, even if all that worked, I am not sure what it should accomplish by now: The group node is not going to crop my image.

Hi @M42, I am sorry I missed that one,

Compose Image will try to create a new image based on the offset information from the input images, it is meant to recompose an image after working on parts of it, e.g finding and calculating features of segments. I will look into giving you a better explanation on how the situation is handled when there are two pixels at the same position and both have a non-background value, but I can’t answer this right away.
Edit: The behaviour in this case is undefined, meaning this is not meant to be used to fuse images that have non-background pixel values at the same location.

I added a workflow that shows how you can create a new blank image with the size of the input and position the cropped image on top of it using GroupBy. Autocropping-Gabriel.knwf (271.1 KB)

best,
Gabriel

@gab1one Thank you very much for the flow! I think it is not yet clear what I want, so I upload a couple of images:

What I put in is

I want to cut out the unimportant stuff. With my workflow I get the mask mask_M42

I can get a black picture from that with either the Image Calculator from my workflow or the Image Generator from yours. In either case I don’t have any offset values anymore.

You flow uses the offset from the cropped image to lay this one and the black image on top of each other, resulting in output_gab1one

However, I wanted to crop the original image and want to get the output output_M42_wants

I am don’t know how to get there even with your flow. There is an Image Cropper node but it seems it does not take the offset values as I wish as flow variables - or I just wasn’t able to find the right parameters (the documentation on the automatic parameter setting is as foggy as usual :cry:).

Hi @M42,
thank you for uploading the example image it helped me a lot and I got very good news for you: :tada:


That is the result of the attached workflow, the trick was to to use Flowvariables to set the desired region in the Image Cropper node.

I feel you, the documentation needs a lot of love at the moment.

PS: here is the workflow: Autocropping-Gabriel-Final.knwf (207.1 KB)

best,
Gabriel

1 Like

Very nice! You found the right parameters :wink: ! That is exactly what I had in mind. Having the parameters as string and in this format… that takes some serious inside knowledge. Is there simple way to contribute to the documentation, specifically I mean the Node Description within KNIME?

Yes, especially the cropper node is one of the worst offenders in that regard.

Currently not really, we are valuing your feedback though and we are planing to make it much easier to contribute in the future.
best,
Gabriel

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.