# How to ask Mathematica to imitate Andy Warhol's pop-art painting?

I tried to ask Mathematica to imitate Andy Warhol, let it convert a Marilyn Monroe's portrait so that it looks like Warhol's world famous pop-art painting. However, the result shown below is far from satisfactory. How can I obtain a better result?

Warhol's world famous pop-art painting:

Result from the code below:

im = Import["https://i.stack.imgur.com/RSKpk.jpg"];
images = {{im, im, im, im}, {im, im, im, im}};
Do[images[[n, m]] = ImagePad[ (Colorize[Binarize[im ] ,
ColorRules -> {0 -> RandomColor[], 1 -> RandomColor[]}
]  ), 6, White] , {n, 1, 2}, {m, 1, 4}] ;

ImageAssemble[images ]

• The first thing I would note is that you are using a binary model. While Andy Warhol seems to be using 4-5 colors. Maybe add 2,3, and 4 to allowed values of the transformation and apply RandomColor to those as well? Sep 8, 2014 at 4:52
• This one seems to be the original Marilyn s2.hubimg.com/u/4262573_f520.jpg Sep 8, 2014 at 7:46
• Perhaps the methods described here will be useful: 55684 Unfortunately my student licence has expired and I can't bring myself to do such heavy image manipulation on my Raspberry Pi.
– shrx
Sep 8, 2014 at 7:57
• Just to note, in case it isn't obvious, that AW manually enhanced his screen prints especially around the eyes and lips. See also sothebys.com/en/news-video/blogs/all-blogs/… Also note the "sloppy" yellow paint above Liz Taylors left eye. Sep 8, 2014 at 15:22
• Use Clustering algorithms. Here's a blog which suggests that's what Warhol did, albeit in analog space. aschinchon.wordpress.com/2014/03/03/warholing-grace-with-clara The code is in R but should be pretty easy to port if desired Sep 9, 2014 at 13:01

# Let's do it Andy's way

So you are Andy. Nice to meet you. And you never got those hands on a computer. It doesn't matter, I will show you!

First you need to go to Marilyn's place. Don't worry, JF isn't there right now. Ask her for a nice photograph and the negatives.

i = ImageCrop@Import@"https://i.stack.imgur.com/W8hV5.png"


Outstanding picture, good work!

Now please, ask the lab to make a fully saturated neg. Yeah, they'll know how. Let me ask a cab for you, you're too high.

ib = ImageResize[Binarize[i, .55], {440,439}]


Ok, now it's your artistic moment. What? Too drunk? I don't care. Just go and paint some stupid doodles all over that pictures. Use your crayons, don't drink the paint.

cr = Import/@ ("https://i.stack.imgur.com/" <> # <> ".png" & /@ {"lnMTz", "8W9Mf", "CD2c9", "E041Z"})


Five minutes! Is that all you can do? OMG! You'll never ever get to be recognized. What a lazy artist you are!

No! Don't go to sleep yet. Wait. You're the artist. What should I do with these shi..mmering red blots?
I'll clip them, so nobody is going to see how you spoiled those beautiful pictures. Leave those Campbell's cans alone and give me the scissors.

chV = ChanVeseBinarize[#, "TargetColor" -> {Gray, Red}] & /@ cr;
Row[Framed /@ chV]


Hey! Andy, I need to make a phone call. Don't touch anything. Get your hands off those paint buckets. You're going to ... too late.

cs = RandomSample[ColorData[22, "ColorList"], 4];
chVcol = MapThread[ColorReplace[#1, {Black -> #2, White -> Black}] &, {chV, cs}]


Ok. so now we have a few silly painted "what should we call them". I hope you are happy now. All that work turned garbage and Marilyn will go mad. Yes! do whatever you want with them. Just leave me alone and tell me where you stock the beer. Collage?, yes, whatever you want I said.

if = Fold[ImageAdd[ImageMultiply[#1, ColorNegate@Binarize@#2], #2] &, chVcol];
ImageMultiply[if, ib]


Let's go to the MoMA, you're late again!

• +1, had a laugh. Also I totally failed to notice the colors of the background and eyebrows are the same, and for the lips and clothes as well.
– shrx
Sep 9, 2014 at 7:35
• as I began reading, I thought it was a joke... it wasn't until the very end when I realized you actually did better than Andy - same effect with much less Obetrol used - kudos!
– user11734
Sep 10, 2014 at 16:50
• @vaxquis I followed the same general procedure, yes. The "scissors-collage" metaphor is not accurate, tough. But I thought the actual process he followed is too cumbersome for intended joke. Sep 10, 2014 at 16:59
• The only thing @ belisarius that made me laugh today. Truman Capote, one of Andy's closest friends, once remarked (I quote by memory): "He's the least intelligent male I know who ever became famous."
– eldo
Sep 10, 2014 at 20:11

Alright, instead of separating the picture by graylevels, I tried to get more involved with component detections. I noticed the original painting has a different color for hair, face, mouth, eyes, and clothes. I tried my best to replicate this.

i = ImageCrop[Import["http://s2.hubimg.com/u/4262573_f520.jpg"]];
id = ImageDimensions[i];
back := Image[RandomColor[], ImageSize -> id];

bw = ChanVeseBinarize[i, Binarize[GradientFilter[i, 1], .05]] //
ColorNegate;
ib = ColorConvert[
RemoveAlphaChannel[
RemoveBackground[i, {"Background", {"Uniform", 0.1}}],
Darker[Gray, 1]], "Grayscale"];
noback = DeleteSmallComponents[ChanVeseBinarize[ib, EdgeDetect[ib]]];

face = Round[FindFaces[bw]][[1]];
Rasterize[
Style[Show[{SetAlphaChannel[bw, 0],
Graphics[{Black, Disk[Mean[face], (Mean[face]/2)*{1, 1.4}]},
Background -> Transparent]}], Antialiasing -> False]];
Black -> RandomColor[Hue[_, _, RandomReal[{.6, 1}]]]];

mouth = ImageTake[
DeleteSmallComponents[
RemoveAlphaChannel[
RemoveBackground[
ImagePad[ImageTrim[bw, face], {{0, 0}, {0, 10}}, Black]],
White] // ColorNegate] // ColorNegate, {11, -1}];
RemoveAlphaChannel[
ColorConvert[
SetAlphaChannel[mouth,
ColorNegate[
Dilation[Closing[ColorNegate[mouth], 30],
DiskMatrix[{2, 5}]]]], "RGB"],
Black], {{face[[1, 1]], id[[1]] - face[[2, 1]]}, {face[[1, 2]],
id[[2]] - face[[2, 2]]}}, White];
mouthc :=
ColorReplace[
SetAlphaChannel[mouth, Binarize[mouth, .9999] // ColorNegate],
Black -> RandomColor[]];

Rasterize[
Overlay[{noback,
eyesNose =
DeleteSmallComponents[Opening[%, 2] // ColorNegate] // ColorNegate;
lines = ImageLines[EdgeDetect[eyesNose], MaxFeatures -> 1][[1]];
eyes = SelectComponents[ColorNegate[eyesNose], "Centroid",
Abs[#[[2]] - Mean[lines[[All, 2]]]] < 20 &] // ColorNegate;
eyes = ImageTake[
RemoveAlphaChannel[
ColorConvert[
SetAlphaChannel[eyes,
ColorNegate[
Dilation[Closing[ColorNegate[eyes], 10],
DiskMatrix[{2, 7}]]]], "RGB"], Black], {{0, 0}, {7, 0}},
White], {8, -1}];
eyesc := ColorReplace[
SetAlphaChannel[eyes, Binarize[eyes] // ColorNegate],
Black -> RandomColor[]];

SetAlphaChannel[ColorConvert[noback, "RGB"], noback];
hair = ImageTake[%, id[[2]] - face[[1, 2]] + 1];
torso = ImageTake[%%, -face[[1, 2]] + 1];
hairTorso :=
ImageAssemble[
Map[ColorReplace[#,
White -> RandomColor[]] &, {{hair}, {torso}}, {2}]];

composition :=
Rasterize[
Overlay[{back,
ImageCompose[mouthc,
SetAlphaChannel[
ColorReplace[bw,
Black -> RandomColor[Hue[_, _, RandomReal[{.05, .5}]]]],
bw // ColorNegate]]]]]}]]

GraphicsGrid[Partition[Table[composition, {8}], 4], ImageSize -> 800]


I'm quite pleased with the result, but the code got kind of long and I'm sure it could be optimiesd.

• +1, very nice. It captures the spirit of the original image set very well. Did you do this on a Raspberry Pi? O_o Sep 8, 2014 at 21:03
• @Pickett I tried to, but FindFaces is not included in the Pi release. I used a friend's computer whose university still has the licence.
– shrx
Sep 8, 2014 at 21:23
• @shrx Are you using the very latest RPi release? (Just curious, I don't have the RPi handy at the moment.) Sep 8, 2014 at 21:24
• @Szabolcs yeah it should be, I update regularly.
– shrx
Sep 8, 2014 at 21:46
• @bobthechemist That's more a confession than an error msg Sep 9, 2014 at 21:33

Making use of the "Posterization" option in ImageEffect:

img = Import@"https://i.stack.imgur.com/yNEqN.png";
awImage := ColorReplace[#, Thread[DominantColors[#] -> RandomColor[4]]] &
[ImageEffect[img, {"Posterization", 2}]]
GraphicsGrid[Partition[Table[awImage, {8}], 4]]


i = Import@"https://i.stack.imgur.com/yNEqN.png";
h = ColorQuantize[ColorSeparate[i, "HSB"][[3]], 4, Dithering -> False];
{4, 4}];
Grid[Map[Image[ImageData@h /. #] &, tr, {2}]]


Here's another way of creating false-color Marilyns: take a greyscale image and apply a Cos[] function to the RGB channels, each with a different frequency parameter:

i = RemoveAlphaChannel@ColorConvert[
ImageCrop@Import@"https://i.stack.imgur.com/W8hV5.png","Grayscale"];
negFunc[x_, par_] := 1 - Cos[2 Pi par x];
imgNegate[im_, r_] := ImageApply[negFunc[#, r] &, im];
GraphicsGrid@Partition[Table[r := RandomReal[{0, 2}];
ColorCombine[{imgNegate[i, r], imgNegate[i, r], imgNegate[i, r]},"RGB"], {k, 12}], 4]


Replacing the Cos with TriangleWave is also quite effective.