-: Okay, say you're designing a coffee shop,
and you want to figure out what are the typical interiors
for your competitors.
So, you wanna understand what type
of furniture they're using, whether they have plants,
or whether there's a chalkboard on the wall
for the menu, like this,
and you want to do that analysis
and see how often certain things come up versus not.
So, one interesting way to do this
is instead of manually looking through a bunch of images,
you could tag them automatically with AI,
because GPT Vision is actually pretty good at this now.
What you need is you have to scrape Google Images,
which is actually the hard part, (chuckles)
but thankfully, there's a tool that does this for you,
so if you just search for Google-Image-Scraper,
yeah, literally just search for Google-Image-Scraper,
and that was the first result,
but however you get the data, it doesn't really matter,
but I assure you it works.
I just, this is in the main.py,
so, when you download this to your computer from GitHub,
then you have this code.
You just put in here what are the different keywords
that you wanna search for?
I downloaded a bunch, and you can see a bunch
of coffee shops in Beijing, coffee shops in Rome,
and then also New York.
We're gonna compare them, potentially.
So, I'm gonna just run an abbreviated part of this analysis.
I would say, by the way, it takes a while to download them,
so, here, I downloaded a bunch, and it doesn't always work.
So, you can see, you get 18 every time, 36 in Sydney,
but once you literally just run Python main.py,
you should see these images start appearing,
but that's not the part I'm gonna teach you,
because that is someone else's code,
and I'll let them teach you that in the README,
but what I'm gonna teach you is what to do
when you have the data, right?
This is a script for the GPT Vision API,
and you just need to run these libraries here,
but I have all the code written here
to pull in what are the different coffee shops, right?
You can see how many photos you've got,
I just looked at the first five here.
See, I've got 45 images from New York,
got a bunch of Sydney, et cetera,
so, what I'm gonna do is I'm just gonna
just little bit just to, wait.
Let's just do Sydney just for testing,
because Vision API is expensive.
If you're running it a bunch of times,
it also takes a little bit of time,
so I'm just gonna write it on these 33 images
in Sydney, right?
And there's two parts to this.
One is inductive coding,
and then the second is deductive coding.
Inductive coding is when you're looking at these,
and you look for patterns,
and you compare them, you go, "Okay, that one has a coffee."
You know, that one has a chalkboard for the menu,
and then there's other ones that have a chalkboard
for menus, as well,
so, maybe that's something that...
Oh, here we go, there's another chalkboard,
so, I've noticed that pattern,
and now that I know there's a pattern,
I wanna find that everywhere.
So, there's another chalkboard,
there's another chalkboard, so, that's deductive coding.
Inductive coding is coming up with the patterns,
comparing and contrasting to find what's different
or what's similar,
and then deductive coding is then going
and finding those patterns everywhere else.
So, we're gonna do those two things here with GPT Vision.
All right, so, the first thing we're doing
is inductive coding,
and we need to be able to send an image to OpenAI,
so, the way that you send an image
is with the Base64 encoding.
This literally just takes an image,
and then turns it into some text
that you can send along with your API call.
And all this code does is it just looks in the folder,
and then it just chooses two images at random
from the different folders,
so, we just have the one folder right now,
but if we have multiple folders,
it would look at all of them.
Oh, I did mention, I forget to mention one thing.
When you're using a Google-Image-Scraper,
you'll probably need to download,
I had to download this mac-x64 Chrome for testing,
but when it's creeping these images, you need that in there.
Here, I'll just put us in a folder called webdriver,
and then it opens that.
I'm just mentioning it because I ran into it.
All right, so, back to the inductive coding.
So, it's choosing an image pair,
it's choosing two images at random,
and then it's comparing them.
So, it's getting the Base64 string,
and then it's using this prompt here.
"Compare these two coffee shops using inductive coding.
What features, attributes, or elements of design
are similar or different?"
And then I'm asking for a structured response here.
That's just how you pass it into GPT Vision, by the way.
You just client.chat.completions,
and then you pass the prompt,
but then you also pass in the two images, as well,
in the same content string.
I'm just using the user prompt here,
but you could also have a system prompt at the top.
So, just run this, see what we've got.
So, it's selected two of these images at random,
number 25 and number 31,
and you can see it takes a little bit of time
for the image response,
as this is OpenAI's biggest model.
Here we go, so now, we've got some labels
that there's some things that they share.
So, coffee shop A and B both have modern designs,
they both have wooden elements.
Only Coffee Shop B has natural light,
and only coffee shop A has spacious interior, right?
So, that's really interesting.
Now, we have some labels, we have a dictionary of labels,
and we can run that and then save it.
So, if we look at, we should have here some cleaned labels.
So, you can see, yeah, there's a bunch of labels here
for these different things, and it's rewritten them.
We've got the actual kind of folder that they're in,
the label, and then the font.
Cool, so now, you have your label dictionary,
and that's useful in itself,
because you could run that multiple times
across multiple images,
so, we just compared two of those images.
You can compare every single image against each other.
Just take a little bit of time.
That, you can run again, as well,
and get a bigger dictionary of data.
Now, it comes to the deductive coding,
and this is the one that's more time consuming,
more expensive.
The reason why I've set this up as asynchronous
is 'cause otherwise it takes a very long time to run,
'cause you're going through every single image, and saying,
and every single label, and going,
"Is this label in this image?
Does this coffee shop have wooden elements?
Does this coffee shop have wooden elements," right?
And then you're going through all the other labels as well.
Does this coffee shop have suspended lighting in it?
Does this coffee shop have seating areas?
There are different tricks for doing this faster or slower,
but for me, I found if I do asynchronous,
means I can get all the labels at once for a single image,
and they all, you know, run quite quickly,
and so, it runs a little bit faster.
So, again, here, we're just passing one image in,
and we're just passing the user prompt,
which is much simpler.
If the label applies to this image, return one,
otherwise return zero, only output one or zero.
All right, if we get a one,
then we are gonna return the label,
and if we don't, then we're not, we're gonna return none.
So, this what this does, this is the asynchronous code.
We just set up a bunch of tasks,
so, we run it for every image,
and then we wait until all the tasks
are done for that image,
it's processing all the labels at the same time,
and OpenAI can handle multiple API calls at the same time.
What will happen is instead of waiting
for each one to come back,
it can process all of them at the same time.
We're gonna get through, say, if we're doing 10 labels,
we'll get through all 10 at the same time
rather than waiting.
If one takes a minute, we're not waiting 10 minutes,
we're getting all of them in one minute,
so, that's the benefit of asynchronous.
Cool, and then we're just gonna return the labels
if the, you know, if the label is in there, right?
And then actually running deductive code,
we just pull open the cleaned_labels.json
that we had before,
and then we have the cleaned labels
which loads the JSON from that dictionary we had,
and then it finds the values.
I've also limited it to just five labels per coffee shop.
Otherwise, it'd take a bit of time.
Cool, all right, so, let me just run this,
and we're processing coffeeshopsydney.
You can see that all three of those
came back at the same time,
but some of them are taking a little bit longer,
but we're not waiting for one to finish
before we get the other.
Cool, so, here we go.
So now, we're processing coffeeshopsydney,
and we'll see how quickly they come back.
Yeah, this is Sydney30.
Okay, now, we're processing Sydney10,
we're getting hanging light fixtures.
So, this is only coming back as positive
if it does have that label, if that makes sense.
Cool, that's where we'll move into analysis but with Vision.
It's really powerful once you figure
how you can apply this to pretty much anything,
like, anytime you have a lot of images,
like maybe in your ads, or on your website,
you can do some analysis to figure out what labels,
and you can define the labels, as well.
You could tell it what sorts of things you're looking for,
give it a list of things.
However you want to do it, that's fine, too.
You could just add new stuff
to this cleaned labels thing, right?
You could just add in some new ideas, right?
Like, I wanna find...
So, this is customers_queuing, right?
I want to find out if there's a barista
that has a tattoo, right?
Like, you could just add that as another option.
Copy, this one has tattooed barista, right?
And it is really funny if the barista's present in this,
but then we're gonna see if they have tattoos,
visible tattoos.
That's how this works,
and then what you're gonna get back
is you're gonna get a file name like this.
This is just a big list of all the different labels, right?
So, it says, coffeeshopnewyork42
has the label, Street View.
This one has the label, Patrons, present,
and then you can do some analysis after this.
Basically, figure out, okay, how many times,
yeah, how many labels does this apply to?
So, how many of the coffee shops has this label?
I'll give you an example.
I'll show you an example here,
because that's still processing,
because it's going through 33 images.
Here's an example from New York that I ran earlier.
So, you can get a list of all the labels into a data frame,
this is like an Excel spreadsheet,
and then you can print out what percentage
of the total images have these different labels.
So here, we're finding that 41% of the patrons,
40% of the coffee shop images show patrons present.
So, to me, you wanna really pay attention
to the ones that are on almost everything,
'cause that's almost like a rule of the game.
If you don't have patrons present in your coffee shop image,
that's probably really bad,
and you definitely want to at least have a stance on that.
Like, maybe have a good reason
for not having patrons present in the image
of your coffee shop when you're uploading that image
to, you know, Google my business,
but you should at least address that.
Have a strategic choice here.
Similarly, for things that are not very popular,
you also might want to think about these
as a differentiator.
So, exposed brick interior, you could argue
that that's not very fashionable anymore,
and that's why only 10% of people have had it,
or you could say, "This is gonna be fashionable.
I can see that this is a trend,
so, I'm gonna start using this," right?
That's how you do this type of analysis.
Obviously, what it doesn't tell you is, like,
which choices to make and what designs to have,
but if you're, you know, not a designer like me,
and you want to build a bit more data to make your decision,
this can help inform your decision,
give you a map of what are the different creative decisions
you need to make when you're doing something designed
or visual, right?
Hopefully that's useful.
This is my little hack for being a data guy,
but also playing in the world of branding.
Hopefully, you find it useful too.