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$
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

| improve this answer | |
$\endgroup$
  • $\begingroup$ Thanks,but where is the polygons? $\endgroup$ – A little mouse on the pampas Feb 11 at 5:17
  • 1
    $\begingroup$ @PleaseCorrectGrammarMistakes, it should be jiggedfaces[vm]; fixed now. $\endgroup$ – kglr Feb 11 at 5:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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