I have tested code from the paper Through the Looking-Glass, and What the Quadratic Camera Found There to understand how they been able to take Figure 1-5. Let use this code to produce Julia set points from the picture inputs[[1]]
inputs = Import /@ {CloudObject[
"https://www.wolframcloud.com/objects/09bf1cae-1109-4490-a35a-\
960ff9199863"],
CloudObject[
"https://www.wolframcloud.com/objects/17390d2b-3271-4c7c-9f0c-\
190db3d81b8c"],
CloudObject[
"https://www.wolframcloud.com/objects/2cc137f2-6a2f-4cd9-9792-\
97c4df3a98b3"],
CloudObject[
"https://www.wolframcloud.com/objects/5c1ce239-7fe8-4636-a008-\
eae8fad0bff8"]}
Now we run code1 I have modified for this answer:
scale = 1;
pic = Image[inputs[[1]]];
dims = ImageDimensions[pic];
pic = ImageResize[pic, scale dims];
dims = ImageDimensions[pic];
complexSize = 2.4 ;
im = Image[
Rasterize[ImagePad[pic, {{0, 0}, {0, 0}}],
RasterSize -> (200; Automatic), ImageResolution -> 300]];
im = ImageResize[im , {200, 200}];
Quiet[LaunchKernels[]];
c = -.83 - I .18; p = 0.;
limitColor = {0.15, 0.95, 0.95};
{xmin, xmax} = {-complexSize, complexSize};
{ymin, ymax} = {-complexSize, complexSize};
{m, n} = ImageDimensions[im];
imm[0] = im; Do[imageData = ImageData[imm[i - 1]];
color1 = With[{c = c, imageData = imageData , m = m, n = n, p = p,
limitColor = limitColor, xmin = xmin, xmax = xmax, ymin = ymin,
ymax = ymax},
Compile[{{z, _Complex}},
Module[{z1}, z1 = z^2 + c;
If[! (xmin <= Re[z1] <= xmax && ymin <= Im[z1] <= ymax), {0, 0,
0}, p limitColor + (1 - p) imageData[[
Round[Max[1, (n (Im[z1] - ymax))/(ymin - ymax)]],
Round[Max[1, (m (Re[z1] - xmin))/(xmax - xmin)]]]]]],
RuntimeAttributes -> {Listable}, Parallelization -> True]];
colors =
color1[Table[
x + I y, {y, ymax, ymin, (ymin - ymax)/n}, {x, xmin, xmax, (
xmax - xmin)/m}]]; imm[i] = Image[colors] ;, {i, 6}]
Table[imm[i], {i, 6}]
Now we run code2 I also have modified for this answer
pic = Import@
CloudObject[
"https://www.wolframcloud.com/objects/09bf1cae-1109-4490-a35a-\
960ff9199863"];
f[z_] := z^2 - .83 - I .18;
Clear[n];
invImage[im_Image] :=
Image[cInvImage[ImageData[im]], ImageSize -> 2 128];
{xmin, xmax} = {-2, 2}; {ymin, ymax} = {-2., 2};
DynamicModule[{a = 0, b = 0, da = 128, db = 128},
pic1 = ImageTake[pic, {a, da}, {b, db}]; {m, n} =
ImageDimensions[pic1]; si[x_] = (x (xmax - xmin))/m + xmin;
sx[i_] = x /. First[Solve[si[x] == i, x]];
sj[y_] = (y (ymax - ymin))/n + ymin;
sy[j_] = y /. First[Solve[sj[y] == j, y]];
fScaled =
ComplexExpand[{Re[f[x + I y]], Im[f[x + I y]]}] /. {x -> si[x],
y -> sj[y]}; fScaledBack = {sx[fScaled[[1]]], sy[fScaled[[2]]]};
intInv = With[{fScaledBack = fScaledBack},
Compile[{{x, _Integer}, {y, _Integer}}, Round[fScaledBack]]];
rgb2 = With[{intInv = intInv, m = m, n = n},
Compile[{{x, _Integer}, {y, _Integer}, {imageData, _Real, 3}},
Module[{x2, y2}, {x2, y2} = intInv[x, y];
If[1 <= x2 < m && 1 <= y2 < n,
imageData[[y2, x2]], {0.`, 0.`, 0.`}]]]];
cInvImage =
With[{rgb2 = rgb2, m = m, n = n},
Compile[{{imageData, _Real, 3}},
Table[rgb2[x, y, imageData], {y, 1, n}, {x, 1, m}]]]];
Visualization
img[0] = pic1; Do[img[i] = invImage[img[i - 1]], {i, 6}]
Table[img[i], {i, 6}]
Therefore in 2 cases we have after 32 iterations some picture similar to inside of filtered picture. Why we can't produce this with standard function like ImageTransformation[]
or with ResourceFunction["ComplexTransformImage"][]
? It is question of scaling. For ImageTransformation[]
we read from tutorials "In 2D, the range of the coordinate system for the input image is assumed to be {{0,1},{0,a}}, where a is the aspect ratio. The bottom-left corner of the image corresponds to coordinates {0,0} by default." Thus first we need to define coordinate system so that we can cover all data we use for Julia set. Second, we compose all pictures in one to get right sequences used Image[Rasterize[Overlay[]]]
. Finally we can make picture from inputs[[4]]
produced by quadratic camera without Julia set. For this we run code from the paper:
screen = Image[inputs[[4]]];
{sm, sn} = ImageDimensions[screen];
backSize = 1000;
twoSquare =
Polygon[{
{{0, 0}, {1, 0}, {1, 1}, {0, 1}},
{{1, 1}, {2, 1}, {2, 2}, {1, 2}}}];
back = Graphics[{Darker[Gray, 0.4], Translate[twoSquare,
Flatten[Table[{i, j}, {i, 0, 8, 2}, {j, 0, 8, 2}], 1]]},
PlotRangePadding -> 0, Frame -> True, FrameTicks -> False,
FrameStyle -> Thick, ImageSize -> backSize];
im = Image[Rasterize[Overlay[{back, screen},
Alignment -> Center]]];
screenOnBackground = Show[im,
Graphics[{Thickness[0.005], Lighter@Yellow,
Circle[Scaled[{0.5, 0.5}], Scaled[1/(2*2.4)]]}],
ImageSize -> 400]
c = 0; (* The circle *)
complexSize = 2.4;
p = 0.2;
limitColor = {0.15, 0.95, 0.95};
{xmin, xmax} = {-complexSize, complexSize};
{ymin, ymax} = {-complexSize, complexSize};
{m, n} = ImageDimensions[im];
imageData = ImageData[im];
color1 = With[
{c = c, imageData = imageData, m = m, n = n, p = p,
limitColor = limitColor, xmin = xmin,
xmax = xmax, ymin = ymin, ymax = ymax},
Compile[{{z, _Complex}},
Module[{z1},
z1 = z^2 + c;
If[! (xmin <= Re[z1] <= xmax && ymin <= Im[z1] <= ymax),
{0, 0, 0},
p*limitColor + (1 - p)*imageData[[
Round[Max[1, (n (Im[z1] - ymax))/
(ymin - ymax)]],
Round[Max[1, (m (Re[z1] - xmin))/
(xmax - xmin)]]]]]],
RuntimeAttributes -> {Listable}]];
colors = color1[Table[x + I*y,
{y, ymax, ymin, (ymin - ymax)/n},
{x, xmin, xmax, (xmax - xmin)/m}]];
im = Image[colors];
screenShows1 = im = ImageTake[im,
{(backSize - sn)/2, backSize - (backSize - sn)/2},
{(backSize - sm)/2, backSize - (backSize - sm)/2}];
cameraSees1 = Show[{im = Image[Rasterize[Overlay[{back, im},
Alignment -> Center]]],
Graphics[{Thickness[0.005], Lighter[Yellow], Circle[Scaled[{0.5, 0.5}], Scaled[1/(2*2.4)]]}]},
ImageSize -> 400]
ResourceFunction["ComplexTransformImage"]
is doing for example:img = Import@ CloudObject[ "https://www.wolframcloud.com/objects/09bf1cae-1109-4490-a35a-960ff9199863"]; julia[z_, c_] := z^2 + c; ResourceFunction["ComplexTransformImage"][img, julia[#1[[1]] + I #1[[2]], 0.3 + 0.6 I] &, 3, 2]
$\endgroup$-.79+i.15
in red and white with a specialPointsize
. The circumference is from a Julia set withComplexTransImage
. For the transition, I do not get a solution so far. Perhaps it is withComplexTransImage
but with a different picture, function. The second is done the same with the same process and so on. $\endgroup$