4
$\begingroup$

I see the method of image segmentation here. enter image description here

I can use the ImagePartition function to divide the image into several regular sub images

img=Import["https://i.stack.imgur.com/vn5ot.jpg"]
ImagePartition[img, 120] // Grid

But how to divide the image into several irregular parts according to this grid: enter image description here

$\endgroup$

1 Answer 1

4
$\begingroup$

Rather than trying to process the puzzle image, we can work with the procedure that produced it (from Vasiliy Kaurov's wonderful blog page Designing Jigsaw Puzzles with Mathematica).

Two things we need to add: (1) We need to get polygon primitives with wiggled edges rather than lines, and (2) We need to use the input image as Texture for polygon primitives rather than graphics background.

ClearAll[bSF, jiggedlines, match, jiggedfaces, vtc, jiggle]

bSF[{p1_, p2_}] := With[{pm = Mean[{p1, p2}], dp = (p2 - p1)/5, 
   rc = RandomChoice[3 {-1, 1}/4]}, 
  BSplineFunction[{p1, pm, pm - dp + rc {1, -1} Reverse[dp], 
    pm + dp + rc {1, -1} Reverse[dp], pm, p2}, 
   SplineWeights -> {1, 15, 25, 25, 15, 1}]]

jiggedlines[mesh_] := Join[MeshPrimitives[mesh, {"Lines", "Boundary"}],
   (Join @@ (MeshPrimitives[mesh, {"Lines", #}] & /@ {"Interior", "Frontier"})) /. 
     Line[x_] /; ArcLength[Line[x]] > 0.25 :> (bSF[x] /@ Subdivide[50])] /. Line[x_] :> x;

match[coords_] := If[#[[{1, -1}]] == coords, #, Reverse@#] &@*
  SelectFirst[#[[{1, -1}]] == coords || #[[{-1, 1}]] == coords &]

jiggedfaces[mesh_] := Module[{jl = jiggedlines[mesh]}, 
   MeshPrimitives[mesh, "Polygons"] /. 
     Polygon[x_] :> Join @@ (match[#][jl] & /@ Partition[x, 2, 1, 1])];

Examples:

image = Import["https://i.stack.imgur.com/MVClL.jpg"];
image = ImageCrop[image, {448, 448}];

id = ImageDimensions[image];
SeedRandom[1]
vm = VoronoiMesh[Transpose[RandomReal[{0, #}, 9] & /@ id],
  Thread[{0, id}], ImageSize -> id];

Row[{Graphics[lines, ImageSize -> 400],
  Graphics[{Opacity[.7], RandomColor[], EdgeForm[Gray], Polygon@#} & /@
     jiggedfaces[vm], ImageSize -> 400]}]

enter image description here

To use the input image as Texture for individual polygons, we need a function to determine VertexTextureCoordinates:

vtc[mesh_] := Transpose[MapThread[Rescale[#, #2] &,
      {Transpose[#], CoordinateBounds[mesh]}]] &;

Texturized puzzle pieces:

pieces = Graphics[{Texture@image, EdgeForm[Gray], 
      Polygon[#, VertexTextureCoordinates -> vtc[vm][#]]}] & /@ jiggedfaces[vm];

Row[Panel /@ {image, 
   Pane[Grid[Partition[pieces, 3]], ImageSize -> {Automatic, 448}, 
    ImageSizeAction -> "ShrinkToFit"]}, Spacer[5]]

enter image description here

Show the pieces together or jiggle location/scale/orientation randomly:

ClearAll[jiggle]
jiggle[ctr_] := Function[{x, y}, Rotate[Translate[Scale[x[[1]], {.95, .95}, y], 
     RandomReal[{.05, .2}] (y - ctr)], RandomReal[{-Pi/16, Pi/16}], y]];

centroids = RegionCentroid @ jiggedfaces[vm];
center = RegionCentroid[vm];

SeedRandom[1]
Row[{Show[pieces, ImageSize -> 400], 
  Graphics[MapThread[jiggle[center], {pieces, centroids}], ImageSize -> 400]}, Spacer[10]]

enter image description here

Replace Texture @ image with

Texture @ Rasterize[Show[RemoveBackground@image, 
   Background -> Opacity[.5, ColorData["Rainbow"][RandomReal[]]]]]

to make pieces with different background colors:

enter image description here

Replace Texture @ image with

Texture @ ImageMultiply[image, Append[ RandomColor[], .3]]

to tint each piece with a random color:

enter image description here

$\endgroup$
2
  • $\begingroup$ Thanks,but where is the polygons? $\endgroup$ Feb 11, 2020 at 5:17
  • 1
    $\begingroup$ @PleaseCorrectGrammarMistakes, it should be jiggedfaces[vm]; fixed now. $\endgroup$
    – kglr
    Feb 11, 2020 at 5:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.