0

I'm running a project about online digital embroidery. For the part of cost calculation, I need to know how many non-continuous blocks in an image. As the image blow, there are 12 blocks in the image.

Origin image:

enter image description here

The result that I expect.

Demo image

Sorry, I can't provide any online coding example for this question. I totally have no idea how to implement this feature. No matter frontend or backend technology, any advice would be appreciated.

peggy
  • 53
  • 5
  • 1
    I would use something like `potrace` to convert the bitmap to a vector, and then count the number of closed strokes in the output (and maybe add 1 for the backrgound). – xenoid Feb 27 '20 at 13:04
  • 1
    You can do that with -connected-components processing. See https://imagemagick.org/script/connected-components.php. Post your input image without the red numbers. – fmw42 Feb 27 '20 at 17:40
  • @xenoid It's interesting. Could you provide any excutable example please? – peggy Mar 02 '20 at 10:25
  • @fmw42 I'm still trying hard to understand how connected-componets work. would be appreciated if there are any other examples. – peggy Mar 02 '20 at 10:29
  • @fmw42 imagemagick convert 1.png -define connected-components:area-threshold=410 -connected-components 4 -auto-level 2.png. After the command, I got an output image. How do I get the amount for the blocks? – peggy Mar 02 '20 at 11:11
  • Add -define connected-components:verbose=true to your command before -connected-components 4 – fmw42 Mar 02 '20 at 22:52
  • @fmw42 I just realized that you need my origin image, sorry about that, the image has added in my question. – peggy Mar 03 '20 at 06:12
  • @fmw42 I've also posted the result on https://imagemagick.org/discourse-server/viewtopic.php?f=1&t=37636. – peggy Mar 03 '20 at 06:15
  • See my reply there. – fmw42 Mar 03 '20 at 17:58

1 Answers1

1

These problems are hard. Even humans will make errors.

Eg the example you provided has 13 blocks, not 12 as I see it. You missed the block between the legs just above 11.

If I am wrong I would argue why is the black (12) of the cup counted it could also be the back of the cat (10).

Flood fill.

A flood fill algorithm can solve the problem. This answer has a simple flood fill algorithm written in JavaScript and using the Canvas 2D API. To use the image must not taint the canvas (same origin or appropriate CORS headers)

Note you will also need to have a fill threshold if the image is anti-aliased or was encoded as jpeg (or other lossy compression)

Note this will only work for images with a few flat colors. Images containing gradients, or shapes that are counted as one but have many colors (due to shadows, lighting, highlights, reflections, etc..) can not be counted using this method.

To count blocks

Rather than fill with a color, fill with alpha = 0 (Transparent).

Steps

Let block count represent number of blocks. Set to 0

Start at the top left most pixel.
Repeat following steps until you have reached bottom right most pixel

Start search
    If the pixel is not transparent 
        Apply the flood fill at that pixel
        Add 1 to block count
        Repeat from start search
    If the pixel is transparent
        move right one pixel, if past right edge move down one and start at left
        Repeat from start search

Once you have competed the steps you will have the number of separate items in the image.

The flood fill algorithm can also easily give you the area of a block, (count the number of pixels filled), give you the size (width, height) and location (top, left, right bottom) of each block.

The only problem will be image noise (due to anti aliasing and compression artifacts). This would give you many small disconnected blocks along color edges. Use the number of pixels in the fill to ignore fills with less than a 100 or so pixels. In the image you provided the smallest block is around 400 pixels in area.

Community
  • 1
  • 1
Blindman67
  • 51,134
  • 11
  • 73
  • 136
  • Wow, really nice explaintion. Yeah, you're correct! it's 13 blocks, I missed one. Could you please write me an excuable example? I'm not very familiar with html5. I've built one which can load image as bitmap data from url https://jsfiddle.net/cqmn5rpa/1/. Could you help me for the part of block amount counting? – peggy Mar 02 '20 at 10:21
  • I have no idea how to do with html5. – peggy Mar 04 '20 at 11:23
  • @peggy This is done via JavaScript (client side) not HTML, or if server side you have many language choices depending on the server you are using. You will need to have some programming experience as there are no off the shelf solutions that I am aware of.Sorry but without that experience there is not much I can do to help. – Blindman67 Mar 04 '20 at 14:46