Title: Analyzing 91 years of Time magazine covers for visual trends - PyImageSearch

URL Source: https://pyimagesearch.com/2015/10/19/analyzing-91-years-of-time-magazine-covers-for-visual-trends/

Published Time: 2015-10-19T14:00:35+00:00

Markdown Content:
[![Image 1: time_analysis_all_covers](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20347'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/10/time_analysis_all_covers.png)

Today’s blog post will build on what we learned from last week: [how to construct an image scraper using Python + Scrapy to scrape ~4,000 _Time_ magazine cover images.](https://pyimagesearch.com/2015/10/12/scraping-images-with-python-and-scrapy/)

So now that we have this dataset, _what are we going to do with it?_

Great question.

One of my favorite visual analysis techniques to apply when examining these types of homogenous datasets is to simply **_average the images together over a given temporal window_** (i.e. timeframe). This average is a straightforward operation. All we need to do is loop over every image in our dataset (or subset) and maintain the _average pixel intensity value_ for **_every_** _(x, y)_\-coordinate.

By computing this average, we can obtain a singular representation of what the image data (i.e. _Time_ magazine covers) looks like over a given timeframe. It’s a simple, yet highly effective method when exploring visual trends in a dataset.

In the remainder of this blog post, we’ll group our _Time_ magazine cover dataset into 10 groups — one group for each of the _**10** **decades**_ _Time_ magazine has been in publication. Then, for each of these groups, we’ll compute the average of all images in the group, giving us a _single_ _visual representation_ of how the _Time_ cover images looked. This average image will allow us to identify _visual trends_ in the cover images; specifically, **marketing and advertising techniques used by _Time_ during a given decade.**

![Image 2](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20128%20128'%3E%3C/svg%3E)

#### Looking for the source code to this post?

[Jump Right To The Downloads Section](#download-the-code)

Before we dive into this post, it might be helpful to read through our previous lesson on [scraping _Time_ magazine cover images](https://pyimagesearch.com/2015/10/12/scraping-images-with-python-and-scrapy/) — reading the previous post is certainly not a requirement, but does help in giving some context.

That said, let’s go ahead and get started. Open up a new file, name it `analyze_covers.py` , and let’s get coding:

\# import the necessary packages
from \_\_future\_\_ import print\_function
import numpy as np
import argparse
import json
import cv2

def filter\_by\_decade(decade, data):
	# initialize the list of filtered rows
	filtered = \[\]

	# loop over the rows in the data list
	for row in data:
		# grab the publication date of the magazine
		pub = int(row\["pubDate"\].split("-")\[0\])

		# if the publication date falls within the current decade,
		# then update the filtered list of data
		if pub >= decade and pub < decade + 10:
			filtered.append(row)

	# return the filtered list of data
	return filtered

**Lines 2-6** simply import our necessary packages — nothing too exciting here.

We then define a utility function, `filter_by_decade` on **Line 8**. As the name suggests, this method will go through our scraped cover images and pull out all covers that fall within a specified decade. Our `filter_by_decade` function requires two arguments: the `decade` we want to grab cover images for, along with `data` , which is simply the `output.json` data from our [previous post](https://pyimagesearch.com/2015/10/12/scraping-images-with-python-and-scrapy/).

Now that our method is defined, let’s move on to the body of the function. We’ll initialize `filtered` , a list of rows in `data` that match our decade criterion (**Line 10**).

We then loop over each `row` in the `data` (**Line 13**), extract the publication date (**Line 15**), and then update our `filtered` list, provided that the publication date falls within our specified `decade` (**Lines 19 and 20**).

Finally, the filtered list of rows is returned to the caller on **Line 23**.

Now that our helper function is defined, let’s move on to parsing command line arguments and loading our `output.json` file:

\# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add\_argument("-o", "--output", required=True,
	help="path to output visualizations directory")
args = vars(ap.parse\_args())

# load the JSON data file
data = json.loads(open("output.json").read())

Again, here the code is quite simple. **Lines 26-29** handle parsing command line arguments. We only need a single switch here, `--visualizations` , which is the path to the directory where we will store our average cover images for each decade between 1920 and 2010.

We then load the `output.json` file on **Line 32** (again, which was generated from our [previous post on scraping images with Python + Scrapy](https://pyimagesearch.com/2015/10/12/scraping-images-with-python-and-scrapy/)).

We are now ready to perform the actual analysis on the _Time_ magazine cover dataset:

\# loop over each individual decade Time magazine has been published
for decade in np.arange(1920, 2020, 10):
	# initialize the magazine covers list
	print("\[INFO\] processing years: {}-{}".format(decade, decade + 9))
	covers = \[\]

	# loop over the magazine issues belonging to the current decade
	for row in filter\_by\_decade(decade, data):
		# load the image
		cover = cv2.imread("output/{}".format(row\["files"\]\[0\]\["path"\]))

		# if the image is None, then there was an issue loading it
		# (this happens for ~3 images in the dataset, likely due to
		# a download problem during the scraping process)
		if cover is not None:
			# resize the magazine cover, flatten it into a single
			# list, and update the list of covers
			cover = cv2.resize(cover, (400, 527)).flatten()
			covers.append(cover)

	# compute the average image of the covers then write the average
	# image to disk
	avg = np.average(covers, axis=0).reshape((527, 400, 3)).astype("uint8")
	p = "{}/{}.png".format(args\["output"\], decade)
	cv2.imwrite(p, avg)

We start by looping over each `decade` between 1920 and 2010 on **Line 35** and initialize a list, `covers` , to store the actual cover images for the current `decade` .

For each of decade, we need to pull out all rows from `output.json` that fall within the decade range. Luckily, this is quite easy since we have our `filter_by_decade` method defined above.

The next step is to load the current cover image from disk on **Line 43**. If the image is `None` , then we know there was an issue loading the cover from disk — this happens for about 3 images in the dataset, which is likely due to a download problem or a network issue during the scraping process.

Provided that the `cover` is not `None` , we we need to resize it to a canonical, known size so we can compute the average of **_each pixel location_** (**Line 51**). Here we resize the image to be a fixed _400 x 527 pixels_, ignoring the aspect ratio — the resized image is then flattened into a list of _400 x 527 x 3= 632,400_ pixels (the _3_ comes from the Red, Green, and Blue channels of the image). If we do not resize the cover to a fixed size, then our rows will not line up and we will be unable to compute the average image for the decade range.

The flattened `cover` is then accumulated into the `covers` list on **Line 52**.

The actual true “analysis” of the decade’s worth of cover images takes place on **Line 56** using the `np.average` function. Every _Time_ magazine cover image is represented by a flattened row in the `covers` list. Therefore, to compute the average of all covers across a decade, all we need to do is take the mean pixel value of each _column_. This will leave us with a single list (again, of _632,400_\-dim), representing the mean value of _each Red, Green, and Blue pixel_ at _each (x, y)-coordinate._

However, since the `avg` image is represented as 1D list of floating point values, we cannot visualize it. First, we need to reshape the `avg` image to have a width of 400 pixels, a height of 527 pixels, and a depth of 3 (for each of the Red, Green, and Blue channels, respectively). Finally, since OpenCV expects 8-bit, unsigned integers, we’ll go ahead and convert to `uint8` from the `float` data type returned from `np.average` .

Finally, **Lines 57 and 58** take our `avg` cover image and write it to disk.

To run our script just execute the following command:

$ python analyze\_covers.py --output visualizations

After a few seconds, you should see the following images in your `visualizations`  directory:

[![Image 3: Figure 1: The output of our analyze_covers.py script for image averaging.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20373'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/10/time_analysis_output.jpg)

**Figure 1:** The output of our analyze\_covers.py script for image averaging.

Results
-------

[![Image 4: Figure 2: Visualizing ten decades' worth of Time magazine covers.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20347'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/10/time_analysis_all_covers.png)

**Figure 2:** Visualizing ten decades’ worth of _Time_ magazine covers.

We now have 10 images in our `visualizations`  directory, an average each for each of the **_10 decades_** _Time_ magazine has been in publication.

But what do these visualizations actually mean? And what types of insights can we gain from examining them?

As it turns out, _**quite a lot**_ — especially with respect to how _Time_ performed **marketing and advertising** with their covers over the past 90+ years:

[![Image 5: Figure 3: Average of Time magazine covers from 1920-1929](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20400%20459'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/10/time_analysis_1920s.png)

**Figure 3:** Average of _Time_ magazine covers from 1920-1929.

*   Originally, the cover of _Time_ magazine was _**ALL**_ black and white. But in the late 1920’s the we can see they started to transfer over to the now iconic red border. However, all other aspects of the cover (including the portrait centerpiece) are still in black and white.
*   The _Time_ logo always appears at the top of the cover.
*   Ornate designs frame the cover portrait on the left and right.

[![Image 6: Figure 4: Average of Time magazine covers from 1930-1939](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20400%20459'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/10/time_analysis_1930s.png)

**Figure 4:** Average of _Time_ magazine covers from 1930-1939.

*   _Time_ is now fully committed to their red border, which has actually grown in thickness slightly.
*   Overall, not much as changed in the design from the 1920’s to the 1930’s.

[![Image 7: Figure 5: Average of Time magazine covers from 1940-1949](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20400%20459'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/10/time_analysis_1940s.png)

**Figure 5:** Average of _Time_ magazine covers from 1940-1949.

*   The first change we notice is that the **red border is not the only color!** The portrait of the cover subject is starting to be printed in color. Given that there seems to be a fair amount of color in the portrait region, this change likely took place in the _early_ 1940’s.
*   Another subtle alternation is the change in _“The Weekly News Magazine”_ typography directly underneath the _“TIME”_ text.
*   It’s also worth noting that the _“TIME”_ text itself is substantially more fixed (i.e. very little variation in placement) as opposed to previous decades.

[![Image 8: Figure 6: Average of Time magazine covers from 1950-1959.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20400%20459'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/10/time_analysis_1950s.png)

**Figure 6:** Average of _Time_ magazine covers from 1950-1959.

*   The 1950’s cover images demonstrate a **_dramatic change_** in _Time_ magazine, both in terms of _**cover format**_ and **_marketing and advertising_**.
*   To start, the portrait, once framed by a white border/ornate designs is now expanded to blanket the _entire cover_ — a trend that continues to the modern day.
*   Meta-information (such as the name of the issue and publication date) have always been published on the magazine covers; however, we are now starting to see a very fixed and highly formatted version of this meta-information in the four corners of the magazine.
*   **Most notable is the change in marketing and advertising by using diagonal yellow bars to highlight the cover story of the issue.**

[![Image 9: Figure 7: Average of Time magazine covers from 1960-1969.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20400%20459'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/10/time_analysis_1960s.png)

**Figure 7:** Average of _Time_ magazine covers from 1960-1969.

*   The first thing you’ll notice about the 1960’s _Time_ cover is a change in the _“TIME”_ text. While the text appears to be purple, it’s actually a transition from _black_ to _red_ (which averages out to be a purple-ish color). All previous decades of _Time_ used black text for their logo, but in the 1960’s we can see that they converted to their now modern day red.
*   Secondly, you’ll see that the _“TIME”_ text is highlighted with a white border which is used to give contrast between the logo and the centerpiece.
*   _Time_ is still using diagonal bars for marketing, allowing them to highlight the cover story — but the bars are now more “white” than they are yellow”. The width of the bars has also been slimmed down by 1/3.

[![Image 10: Figure 8: Average of Time magazine covers from 1970-1979.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20400%20459'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/10/time_analysis_1970s.png)

**Figure 8:** Average of _Time_ magazine covers from 1970-1979.

*   **Here we see another big change in marketing and advertising strategy** — _Time_ is starting to use **faux page folds** (top-right corner), allowing us to get a “sneak peek” of what’s inside the issue.
*   **Also note the barcode that is starting to appear in the bottom-left corner of the issue.**
*   The white border surrounding the _“TIME”_ text has been removed.

[![Image 11: Figure 9: Average of Time magazine covers from 1980-1989.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20400%20459'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/10/time_analysis_1980s.png)

**Figure 9:** Average of _Time_ magazine covers from 1980-1989.

*   The 1980’s issues of _Time_ seem to continue the same faux page fold marketing strategy from the 1970’s.
*   They also have re-inserted the white border surrounding the _“TIME”_ text.
*   A barcode is now predominately used in the bottom-left corner.
*   **But also note that a barcode is starting to appear in the bottom-right corner as well.**

[![Image 12: Figure 10: Average of Time magazine covers from 1990-1999.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20400%20459'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/10/time_analysis_1990s.png)

**Figure 10:** Average of _Time_ magazine covers from 1990-1999.

*   Once again, the white border surrounding _“TIME”_ is gone — it makes me curious what types of split tests they were running during these years to figure out if the white border contributed to more sales of the magazine.
*   The barcode now consistently appears on the bottom-left and bottom-right corners of the magazine, the choice of barcode placement being highly dependent on aesthetics.
*   Also notice that the faux page fold which, which survived nearly two decades, is now gone.
*   Lastly, note how the _“TIME”_ logo has become quite variable in size.

[![Image 13: Figure 11: Average of Time magazine covers from 2000-2009.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20400%20459'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/10/time_analysis_2000s.png)

**Figure 11:** Average of _Time_ magazine covers from 2000-2009.

*   The variable logo size has become more pronounced in the 2000’s era.
*   **We can also see the barcode is completely gone.**

[![Image 14: Figure 12: Average of Time magazine covers from 2010-Present.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20400%20459'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2015/10/time_analysis_2010s.png)

**Figure 12:** Average of _Time_ magazine covers from 2010-Present.

*   We now arrive at the modern day _Time_ magazine cover.
*   Overall, there isn’t much difference between the 2010’s and 2000’s.
*   However, the size of the _Time_ logo itself seems to be _substantially_ less varied, and only fluctuates along the _y_\-axis.

### What's next? We recommend [PyImageSearch University](https://pyimagesearch.com/pyimagesearch-university/?utm_source=blogPost&utm_medium=bottomBanner&utm_campaign=What%27s%20next%3F%20I%20recommend).

**Course information:**  
84 total classes • 114+ hours of on-demand code walkthrough videos • Last updated: February 2024  
★★★★★ 4.84 (128 Ratings) • 16,000+ Students Enrolled

**I strongly believe that if you had the right teacher you could _master_ computer vision and deep learning.**

Do you think learning computer vision and deep learning has to be time-consuming, overwhelming, and complicated? Or has to involve complex mathematics and equations? Or requires a degree in computer science?

That’s _not_ the case.

All you need to master computer vision and deep learning is for someone to explain things to you in _simple, intuitive_ terms. _And that’s exactly what I do_. My mission is to change education and how complex Artificial Intelligence topics are taught.

If you're serious about learning computer vision, your next stop should be PyImageSearch University, the most comprehensive computer vision, deep learning, and OpenCV course online today. Here you’ll learn how to _successfully_ and _confidently_ apply computer vision to your work, research, and projects. Join me in computer vision mastery.

**Inside PyImageSearch University you'll find:**

*   ✓ **84 courses** on essential computer vision, deep learning, and OpenCV topics
*   ✓ **84 Certificates** of Completion
*   ✓ **114+ hours** of on-demand video
*   ✓ **Brand new courses released _regularly_**, ensuring you can keep up with state-of-the-art techniques
*   ✓ **Pre-configured Jupyter Notebooks in Google Colab**
*   ✓ Run all code examples in your web browser — works on Windows, macOS, and Linux (no dev environment configuration required!)
*   ✓ Access to **centralized code repos for _all_ 536+ tutorials** on PyImageSearch
*   ✓ **Easy one-click downloads** for code, datasets, pre-trained models, etc.
*   ✓ **Access** on mobile, laptop, desktop, etc.

[Click here to join PyImageSearch University](https://pyimagesearch.com/pyimagesearch-university/?utm_source=blogPost&utm_medium=bottomBanner&utm_campaign=What%27s%20next%3F%20I%20recommend)

Summary
-------

In this blog post we explored our _Time_ magazine cover dataset which we gathered in the [previous lesson](https://pyimagesearch.com/2015/10/12/scraping-images-with-python-and-scrapy/).

To perform a visual analysis of the dataset and identify trends and changes in the magazine covers, we _averaged_ covers together across multiple decades. Given the ten decades _Time_ has been in publication, this left us with ten separate visual representations.

Overall, the changes in covers may seem subtle, but they are actually quite insightful to how the magazine has evolved, **specifically in regards to marketing and advertising.**

The changes in:

1.  Logo color and white bordering
2.  Banners to highlight the cover story
3.  And faux page folds

Clearly demonstrate that _Time_ magazine was trying to determine which strategies were “eye catching” enough for readers to grab a copy off their local newsstand.

Furthermore, their flip-flopping between white bordering and no white bordering indicates to me that they were performing a series of split tests, accumulating _decades worth of data_, that eventually resulted in their current, modern day logo.

![Image 15](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20410%20567'%3E%3C/svg%3E)

#### Download the Source Code and FREE 17-page Resource Guide

Enter your email address below to get a .zip of the code and a **FREE 17-page Resource Guide on Computer Vision, OpenCV, and Deep Learning.** Inside you'll find my hand-picked tutorials, books, courses, and libraries to help you master CV and DL!