In MSE by a similar problem about the optical illusion, but I feel that the solution ideas of other problems can not be applied to the following diagram, I would like to ask you how to draw this kind of diagram? I don't have any ideas.
3 Answers
The image in blue and pink has been overlayed with small boxes in black and white. At the cordners of each box protrudes a line with same color as the corner half way to the next box. Every second box in x and y direction is rotated by 180° and in addition in the pink area by another 90°.
im = Image[ImagePad[Binarize[
Import["https://image.spreadshirtmedia.net/image-server/v1/products/T1459A839PA4459PT28D16690413W9915H10000/views/1,width=120,height=120,appearanceId=839,backgroundColor=F2F2F2/cat-icon-sticker.jpg"]
], 50, 1], ImageResolution -> 72];
ClearAll[box]
box[x_, y_, d_:1, s_:0.17] := Translate[{
Black,
Polygon[(Plus[d])*{{0, s}, {s, 0}, {s, -s}/2, {-s, s}/2}],
Line[d*{{0, s}, {0, 0.5}}],
Line[d*{{s, 0}, {0.5, 0}}],
White,
Polygon[(-d)*{{0, s}, {s, 0}, {s, -s}/2, {-s, s}/2}],
Line[(-d)*{{0, s}, {0, 0.5}}],
Line[(-d)*{{s, 0}, {0.5, 0}}]
}, {x, y}]
dat = Transpose[Reverse[ImageData[im]]];
{px, py} = Dimensions[dat]
n = 20;
boxes = Table[Module[{
x = (i - 1) / (n - 1) * px,
y = (j - 1) / (n - 1) * py
},
phi = Pi/2 +
Pi * Mod[i + j, 2] +
Pi / 2 *dat[[Round[i * px / n],Round[j * py / n]]];
Rotate[box[x, y, px / (n - 1)], phi]
], {i, n}, {j, n}];
Graphics[{
ColorReplace[im, {
0 -> RGBColor[1, 0.6, 0.8],
1 -> RGBColor[0.4, 0.8, 1]
}],
boxes
}, ImageSize -> 800]
-
4$\begingroup$ Cool! But this image has a flaw: parts of the blue region appears to belong to the elevated pink region: Specifically, immediately below the cat's face, a bit to the left and right (especially to the left). Maybe this is caused by the presence of a few black and white squares surrounded by blue faces that are aligned -45 deg instead of the expected +45 deg in the blue layer. $\endgroup$ Commented Oct 21, 2023 at 12:32
-
$\begingroup$ @AndreasRejbrand Also note that in the example, the vertical lines in the overlay switch color precisely on borders between blue and pink, where in this result it happens exactly halfway across the lines in areas that are more or less directly underneath a border. (@azerbajdzan's solution does this correctly, except on the horizontal lines instead.) $\endgroup$ Commented Oct 21, 2023 at 20:34
I'll post the code tomorrow, it's a bit of a mess at the moment.
Here is the code with abusing of GriGraph
for a little piece of art.
n = 11;
r = {{-(1/2), 0}, {1/2, 0}, {1/2, 1/2}, {-(1/2), 1/2}};
{c1, c2} = {RGBColor[0.4, 0.8, 1], RGBColor[1, 0.6, 0.8]};
vs[fi_, r_] :=
Graphics[{Black, Polygon[RotationMatrix[fi] . # & /@ (-r)], White,
Polygon[RotationMatrix[fi] . # & /@ r]}];
g = GridGraph[{2 n + 1, 2 n + 1}, EdgeStyle -> Black,
VertexShape -> {Alternatives @@ Range[1, (2 n + 1)^2, 2] ->
vs[-π/4, r],
Alternatives @@ Range[2, (2 n + 1)^2, 2] -> vs[3 π/4, r]},
VertexSize -> 0.4, Background -> c1, ImageSize -> 720];
AnnotationValue[g,
EdgeStyle] = {Alternatives @@ Select[EdgeList[g], OddQ[#[[1]]] &] ->
White};
h = GridGraph[{2 n + 1, 2 n + 1}, EdgeStyle -> Black,
VertexShape -> {Alternatives @@ Range[1, (2 n + 1)^2, 2] ->
vs[π/4, r],
Alternatives @@ Range[2, (2 n + 1)^2, 2] -> vs[-3 π/4, r]},
VertexSize -> 0.4, Background -> c2, ImageSize -> 720];
AnnotationValue[h,
VertexCoordinates] = {2 n +
2 - #[[1]], #[[2]]} & /@ (AnnotationValue[{h, #},
VertexCoordinates] & /@ Range[(2 n + 1)^2]);
AnnotationValue[h,
EdgeStyle] = {Alternatives @@ Select[EdgeList[g], OddQ[#[[1]]] &] ->
White};
im = ColorNegate@
Graphics[{Disk[], White, Disk[{-0.32, 0.54}, 1/5],
Disk[{0.32, 0.54}, 1/5],
Disk[{0, -0.15}, 3/5, {π, 2 π}]}, PlotRange -> 1.25,
ImageSize -> 720];
ImageCompose[Image@g, SetAlphaChannel[Image@h, im]]
Just an alternative relying on image operations and using some emojis as input for testing purpose:
emoji = "🐬"(*"🐎"*)(*"🐖"*)(*"🐘"*);
imgSize = {800, 800};
colors = <|"back" -> RGBColor[0.4, 0.8, 1], "front" -> RGBColor[1, 0.6, 0.8]|>;
image = Image[ Rasterize@Magnify[emoji, 40] // Binarize // RemoveBackground //
ColorReplace[#, Black -> colors["front"]] &];
mask = Image[Graphics[{{
Inset[Graphics[image // ColorReplace[#, colors["front"] -> Black] &,
ImageSize -> imgSize], Center]}}, ImageSize -> imgSize], ImageResolution -> 500];
transform[image_, direction_ : "<" | ">", background_ : colors["back"], steps_ : 20] :=
Module[{size = 7},
colLineColor[x_, y_] := If[EvenQ[x + y], Black, White];
rowLineColor[x_, y_] :=
If[If[direction == "<", EvenQ, OddQ][x + y], Black, White];
theta = If[direction == "<", 45 °, 135 °];
Image[Graphics[{
{Inset[Graphics[image, ImageSize -> imgSize], Center]}
, Table[{
colLineColor[x, y]
, Line[{{x + 1, y}, {x + 1 , Min[y + size, steps size]}}]
, rowLineColor[x, y]
, Line[{{x, y + 1}, {Min[x + size, steps size] , y + 1}}]
, Rotate[#[x, y], If[EvenQ[x + y], theta, theta + 180 °]] }
, {x, 0, steps size, size}, {y, 0, steps size, size}] &[
{x, y} |-> {White, Rectangle[{x, y}, {x + 1, y + 2}]
, Black, Rectangle[{x + 1, y}, {x + 2, y + 2}]}]}
, Background -> background, ImageSize -> imgSize], ImageResolution -> 500]]
backgroundImage = ImageAdd[ImageMultiply[transform[image, "<"], mask],ColorNegate@mask] ;
frontImage = ColorNegate@ImageMultiply[transform[image, ">", White], ColorNegate@mask] //
ColorReplace[#, {ColorNegate@colors["front"] -> colors["front"]}] &;
Grid[{{backgroundImage, frontImage}}]
(* Output *)
(* Putting them together *)
ImageDifference[ColorNegate@backgroundImage, frontImage]
Graphics
andRectangle
. $\endgroup$