Reputation: 636
I need some help in estimating somekind of of morphological operations(preferably using skimage or scipy image or python in general) that can help me isolate the regions that are enclosed by all sides(see images.) The problem is the outer shell can be of varied shape and size. The enclosed regions are also of varied shapes and sizes. Examples of the image where the enclosed(by the white regions) black region needs to isolated.
By isolation I mean to get all the pixel coordinates in the enclosed black regions.
Example 1
Example 2
Also another caveat is that the images like this should not be filled up.
Upvotes: 0
Views: 152
Reputation: 207818
I prefer @Juan's solution, but just for fun, here's a slightly different approach. Floodfill with white starting from the top-left corner and your fully-enclosed pixels will be all that is left over.
#!/usr/bin/env python3
import numpy as np
from skimage.segmentation import flood_fill
import cv2
im = cv2.imread('scan.png', cv2.IMREAD_GRAYSCALE)
# Fill with white from top-left
filled = flood_fill(im, (0, 0), 255)
# Save result
cv2.imwrite('DEBUG-result.png', filled)
# Get list of black pixels
blk = np.where(filled==0)
print(f'Number of fully enclosed black pixels: {len(blk[0])}')
print(blk)
So that you can see the extent of the image, I have artificially added a red border:
Here is the output:
Number of fully enclosed black pixels: 957
(array([364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364,
364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364, 364,
364, 364, 364, 364, 364, 364, 364, 365, 365, 365, 365, 365, 365,
365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365,
365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365, 365,
365, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366,
366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366, 366,
366, 366, 366, 366, 366, 366, 366, 366, 367, 367, 367, 367, 367,
367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367,
367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367,
367, 367, 367, 367, 367, 368, 368, 368, 368, 368, 368, 368, 368,
368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368,
368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368,
368, 368, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369,
369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369,
369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 369, 370,
370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370,
370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370,
370, 370, 370, 370, 370, 370, 370, 370, 370, 371, 371, 371, 371,
371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371,
371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371,
371, 371, 371, 371, 371, 371, 372, 372, 372, 372, 372, 372, 372,
372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
372, 372, 372, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373,
373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 373,
373, 373, 373, 373, 373, 373, 373, 373, 373, 373, 374, 374, 374,
374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374,
374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374, 374,
374, 374, 374, 374, 375, 375, 375, 375, 375, 375, 375, 375, 375,
375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375,
375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, 376, 376,
376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376,
376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376, 376,
376, 376, 376, 376, 376, 377, 377, 377, 377, 377, 377, 377, 377,
377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377,
377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 377, 378,
378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378,
378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378,
378, 378, 378, 378, 378, 378, 379, 379, 379, 379, 379, 379, 379,
379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379,
379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379, 379,
380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380,
380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380,
380, 380, 380, 380, 380, 380, 380, 381, 381, 381, 381, 381, 381,
381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381,
381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381,
381, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382,
382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382,
382, 382, 382, 382, 382, 382, 382, 382, 383, 383, 383, 383, 383,
383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383,
383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383, 383,
383, 383, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384,
384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384, 384,
384, 384, 384, 384, 384, 384, 384, 384, 384, 385, 385, 385, 385,
385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385,
385, 385, 385, 385, 385, 385, 385, 386, 386, 386, 386, 386, 386,
386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386, 386,
386, 386, 386, 386, 386, 387, 387, 387, 387, 387, 387, 387, 387,
387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387, 387,
387, 387, 387, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388,
388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 389, 389,
389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389,
389, 389, 389, 389, 389, 389, 390, 390, 390, 390, 390, 390, 390,
390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390,
390, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
391, 391, 391, 392, 392, 392, 392, 392, 392, 392, 392, 392, 392,
392, 392, 392, 392, 392, 393, 393, 393, 393, 393, 393, 393, 393,
393, 393, 393, 393, 393, 393, 393, 394, 394, 394, 394, 394, 394,
394, 394, 394, 394, 394, 394, 394, 394, 394, 395, 395, 395, 395,
395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, 396, 396,
396, 396, 396, 396, 396, 396, 396, 397, 397, 397, 397, 397, 397,
397, 397, 397, 398, 398, 398, 398, 398, 398, 398, 398, 398, 399,
399, 399, 400, 400, 400, 401, 401, 401]), array([244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256,
257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269,
270, 271, 272, 273, 274, 275, 276, 244, 245, 246, 247, 248, 249,
250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262,
263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275,
276, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268,
269, 270, 271, 272, 273, 274, 275, 276, 241, 242, 243, 244, 245,
246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258,
259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271,
272, 273, 274, 275, 276, 241, 242, 243, 244, 245, 246, 247, 248,
249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261,
262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 241,
242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267,
268, 269, 270, 271, 272, 273, 274, 275, 276, 241, 242, 243, 244,
245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257,
258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270,
271, 272, 273, 274, 275, 276, 241, 242, 243, 244, 245, 246, 247,
248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260,
261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
274, 275, 276, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250,
251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263,
264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 241, 242, 243,
244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256,
257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269,
270, 271, 272, 273, 241, 242, 243, 244, 245, 246, 247, 248, 249,
250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262,
263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 241, 242,
243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268,
269, 270, 271, 272, 273, 241, 242, 243, 244, 245, 246, 247, 248,
249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261,
262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 241,
242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267,
268, 269, 270, 271, 272, 273, 241, 242, 243, 244, 245, 246, 247,
248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260,
261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266,
267, 268, 269, 270, 271, 272, 273, 241, 242, 243, 244, 245, 246,
247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259,
260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272,
273, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
266, 267, 268, 269, 270, 271, 272, 273, 241, 242, 243, 244, 245,
246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258,
259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271,
272, 273, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 253, 254, 255, 256,
257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269,
270, 271, 272, 273, 274, 275, 276, 253, 254, 255, 256, 257, 258,
259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271,
272, 273, 274, 275, 276, 253, 254, 255, 256, 257, 258, 259, 260,
261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
274, 275, 276, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 256, 257,
258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270,
271, 272, 273, 274, 275, 276, 256, 257, 258, 259, 260, 261, 262,
263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275,
276, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270,
271, 272, 273, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268,
269, 270, 271, 272, 273, 259, 260, 261, 262, 263, 264, 265, 266,
267, 268, 269, 270, 271, 272, 273, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 259, 260, 261, 262,
263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 262, 263,
264, 265, 266, 267, 268, 269, 270, 262, 263, 264, 265, 266, 267,
268, 269, 270, 262, 263, 264, 265, 266, 267, 268, 269, 270, 265,
266, 267, 265, 266, 267, 265, 266, 267]))
Hopefully you can see from the first element of each array that the first black pixel is at 364,244
Note that, if there is the possibility that the scan would touch the edge of the image, the flood-fill will fail to "flow" all the way around the edges. In this case, you can simply add a 1-pixel wide black border all the way around the edge for the floodfill to flow around... and remove it afterwards.
Upvotes: 1
Reputation: 5768
Use scipy.ndimage.binary_fill_holes
from scipy import ndimage as ndi
filled = ndi.binary_fill_holes(image)
holes = filled - image # or np.logical_xor(filled, image)
Upvotes: 3