0% found this document useful (0 votes)
16 views10 pages

REF3 - Histograms

Uploaded by

Carlos Delgado
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views10 pages

REF3 - Histograms

Uploaded by

Carlos Delgado
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 10

1.

IMAGE HISTOGRAMS

GRAYSCALE HISTOGRAMS

# import the necessary packages


from matplotlib import pyplot as plt
import argparse
import cv2
# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True,
help="path to the image")
args = vars(ap.parse_args())
# load the input image and convert it to grayscale
image = cv2.imread(args["image"])
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# compute a grayscale histogram
hist = cv2.calcHist([image], [0], None, [256], [0, 256])
# matplotlib expects RGB images so convert and then display the image
# with matplotlib
plt.figure()
plt.axis("off")
plt.imshow(cv2.cvtColor(image, cv2.COLOR_GRAY2RGB))
# plot the histogram
plt.figure()
plt.title("Grayscale Histogram")
plt.xlabel("Bins")
plt.ylabel("# of Pixels")
plt.plot(hist)
plt.xlim([0, 256])
# normalize the histogram
hist /= hist.sum()
# plot the normalized histogram
plt.figure()
plt.title("Grayscale Histogram (Normalized)")
plt.xlabel("Bins")
plt.ylabel("% of Pixels")
plt.plot(hist)
plt.xlim([0, 256])
plt.show()
COLOR HISTOGRAMS

from matplotlib import pyplot as plt


import argparse
import imutils
import cv2
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="path to the image")
args = vars(ap.parse_args())
image = cv2.imread(args["image"])
# split the image into its respective channels, then initialize the tuple of channel names
# along with our figure for plotting
chans = cv2.split(image)
colors = ("b", "g", "r")
plt.figure()
plt.title("'Flattened' Color Histogram")
plt.xlabel("Bins")
plt.ylabel("# of Pixels")
# loop over the image channels
for (chan, color) in zip(chans, colors):
# create a histogram for the current channel and plot it
hist = cv2.calcHist([chan], [0], None, [256], [0, 256])
plt.plot(hist, color=color)
plt.xlim([0, 256])
# create a new figure and then plot a 2D color histogram for the green and blue channels
fig = plt.figure()
ax = fig.add_subplot(131)
hist = cv2.calcHist([chans[1], chans[0]], [0, 1], None, [32, 32],
[0, 256, 0, 256])
p = ax.imshow(hist, interpolation="nearest")
ax.set_title("2D Color Histogram for G and B")
plt.colorbar(p)
# plot a 2D color histogram for the green and red channels
ax = fig.add_subplot(132)
hist = cv2.calcHist([chans[1], chans[2]], [0, 1], None, [32, 32],
[0, 256, 0, 256])
p = ax.imshow(hist, interpolation="nearest")
ax.set_title("2D Color Histogram for G and R")
plt.colorbar(p)
# plot a 2D color histogram for blue and red channels
ax = fig.add_subplot(133)
hist = cv2.calcHist([chans[0], chans[2]], [0, 1], None, [32, 32],
[0, 256, 0, 256])
p = ax.imshow(hist, interpolation="nearest")
ax.set_title("2D Color Histogram for B and R")
plt.colorbar(p)
# finally, let's examine the dimensionality of one of the 2D histograms
print("2D histogram shape: {}, with {} values".format(
hist.shape, hist.flatten().shape[0]))
# our 2D histogram could only take into account 2 out of the 3 channels in the image so now
# let's build a 3D color histogram (utilizing all channels) with 8 bins in each direction
# -- we can't plot the 3D histogram, but the theory is exactly like that of a 2D histogram,
# so we'll just show the shape of the histogram
hist = cv2.calcHist([image], [0, 1, 2],
None, [8, 8, 8], [0, 256, 0, 256, 0, 256])
print("3D histogram shape: {}, with {} values".format(
hist.shape, hist.flatten().shape[0]))
# display the original input image and our plots
plt.figure()
plt.axis("off")
plt.imshow(imutils.opencv2matplotlib(image))
plt.show()
HISTOGRAMS FOR SPECIFIC (MASKED) REGIONS

# import the necessary packages


from matplotlib import pyplot as plt
import numpy as np
import cv2
def plot_histogram(image, title, mask=None):
# split the image into its respective channels, then initialize
# the tuple of channel names along with our figure for plotting
chans = cv2.split(image)
colors = ("b", "g", "r")
plt.figure()
plt.title(title)
plt.xlabel("Bins")
plt.ylabel("# of Pixels")
# loop over the image channels
for (chan, color) in zip(chans, colors):
# create a histogram for the current channel and plot it
hist = cv2.calcHist([chan], [0], mask, [256], [0, 256])
plt.plot(hist, color=color)
plt.xlim([0, 256])
# load the beach image and plot a histogram for it
image = cv2.imread("beach.png")
plot_histogram(image, "Histogram for Original Image")
cv2.imshow("Original", image)
# construct a mask for our image; our mask will be *black* for regions
# we want to *ignore* and *white* for regions we want to *examine*
mask = np.zeros(image.shape[:2], dtype="uint8")
cv2.rectangle(mask, (60, 290), (210, 390), 255, -1)
cv2.imshow("Mask", mask)
# display the masked region
masked = cv2.bitwise_and(image, image, mask=mask)
cv2.imshow("Applying the Mask", masked)
# compute a histogram for our image, but we'll only include pixels in
# the masked region
plot_histogram(image, "Histogram for Masked Image", mask=mask)
# show our plots
plt.show()
2. HISTOGRAM EQUALIZATION

SIMPLE HISTOGRAM EQUALIZATION

# import the necessary packages


import argparse
import cv2
# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", type=str, required=True, help="path to image")
args = vars(ap.parse_args())
# load the input image from disk and convert it to grayscale
print("[INFO] loading input image...")
image = cv2.imread(args["image"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# apply histogram equalization
print("[INFO] performing histogram equalization...")
equalized = cv2.equalizeHist(gray)
# show the original grayscale image and equalized image
cv2.imshow("Input", gray)
cv2.imshow("Histogram Equalization", equalized)
cv2.waitKey(0)
ADAPTIVE HISTOGRAM EQUALIZATION

# import the necessary packages


import argparse
import cv2
# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", type=str, required=True, help="path to image")
ap.add_argument("-c", "--clip", type=float, default=2.0,
help="threshold for contrast limiting")
ap.add_argument("-t", "--tile", type=int, default=8,
help="tile grid size -- divides image into tile x time cells")
args = vars(ap.parse_args())
# load the input image from disk and convert it to grayscale
print("[INFO] loading input image...")
image = cv2.imread(args["image"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# apply CLAHE (Contrast Limited Adaptive Histogram Equalization)
print("[INFO] applying CLAHE...")
clahe = cv2.createCLAHE(clipLimit=args["clip"],
tileGridSize=(args["tile"], args["tile"]))
equalized = clahe.apply(gray)
# show the original grayscale image and CLAHE output image
cv2.imshow("Input", gray)
cv2.imshow("CLAHE", equalized)
cv2.waitKey(0)
3. HISTOGRAM MATCHING

# import the necessary packages


from skimage import exposure
import matplotlib.pyplot as plt
import argparse
import cv2
# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-s", "--source", required=True,
help="path to the input source image")
ap.add_argument("-r", "--reference", required=True,
help="path to the input reference image")
args = vars(ap.parse_args())
# load the source and reference images
print("[INFO] loading source and reference images...")
src = cv2.imread(args["source"])
ref = cv2.imread(args["reference"])
# determine if we are performing multichannel histogram matching
# and then perform histogram matching itself
print("[INFO] performing histogram matching...")
multi = True if src.shape[-1] > 1 else False
matched = exposure.match_histograms(src, ref, multichannel=multi)
# show the output images
cv2.imshow("Source", src)
cv2.imshow("Reference", ref)
cv2.imshow("Matched", matched)
cv2.waitKey(0)
# construct a figure to display the histogram plots for each channel
# before and after histogram matching was applied
(fig, axs) = plt.subplots(nrows=3, ncols=3, figsize=(8, 8))
# loop over our source image, reference image, and output matched image
for (i, image) in enumerate((src, ref, matched)):
# convert the image from BGR to RGB channel ordering
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# loop over the names of the channels in RGB order
for (j, color) in enumerate(("red", "green", "blue")):
# compute a histogram for the current channel and plot it
(hist, bins) = exposure.histogram(image[..., j], source_range="dtype")
axs[j, i].plot(bins, hist / hist.max())
# compute the cumulative distribution function for the
# current channel and plot it
(cdf, bins) = exposure.cumulative_distribution(image[..., j])
axs[j, i].plot(bins, cdf)
# set the y-axis label of the current plot to be the name
# of the current color channel
axs[j, 0].set_ylabel(color)
# set the axes titles
axs[0, 0].set_title("Source")
axs[0, 1].set_title("Reference")
axs[0, 2].set_title("Matched")
# display the output plots
plt.tight_layout()
plt.show()
4. GAMMA CORRECTION
# import the necessary packages
from __future__ import print_function
import numpy as np
import argparse
import cv2
def adjust_gamma(image, gamma=1.0):
# build a lookup table mapping the pixel values [0, 255] to
# their adjusted gamma values
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
# apply gamma correction using the lookup table
return cv2.LUT(image, table)
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="path to input image")
args = vars(ap.parse_args())
# load the original image
original = cv2.imread(args["image"])
# loop over various values of gamma
for gamma in np.arange(0.5, 1.5, 2.0):
# ignore when gamma is 1 (there will be no change to the image)
if gamma == 1:
continue
# apply gamma correction and show the images
gamma = gamma if gamma > 0 else 0.1
adjusted = adjust_gamma(original, gamma=gamma)
cv2.putText(adjusted, "g={}".format(gamma), (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3)
cv2.imshow("Images", np.hstack([original, adjusted]))
cv2.waitKey(0)
5. AUTOMATIC COLOR CORRECTION

# import the necessary packages


from imutils.perspective import four_point_transform
from skimage import exposure
import numpy as np
import argparse
import imutils
import cv2
import sys

def find_color_card(image):
# load the ArUCo dictionary, grab the ArUCo parameters, and
# detect the markers in the input image
arucoDict = cv2.aruco.Dictionary_get(cv2.aruco.DICT_ARUCO_ORIGINAL)
arucoParams = cv2.aruco.DetectorParameters_create()
(corners, ids, rejected) = cv2.aruco.detectMarkers(image,
arucoDict, parameters=arucoParams)
# try to extract the coordinates of the color correction card
try:
# otherwise, we've found the four ArUco markers, so we can
# continue by flattening the ArUco IDs list
ids = ids.flatten()
# extract the top-left marker
i = np.squeeze(np.where(ids == 923))
topLeft = np.squeeze(corners[i])[0]
# extract the top-right marker
i = np.squeeze(np.where(ids == 1001))
topRight = np.squeeze(corners[i])[1]
# extract the bottom-right marker
i = np.squeeze(np.where(ids == 241))
bottomRight = np.squeeze(corners[i])[2]
# extract the bottom-left marker
i = np.squeeze(np.where(ids == 1007))
bottomLeft = np.squeeze(corners[i])[3]
# we could not find color correction card, so gracefully return
except:
return None
# build our list of reference points and apply a perspective
# transform to obtain a top-down, bird’s-eye view of the color
# matching card
cardCoords = np.array([topLeft, topRight, bottomRight, bottomLeft])
card = four_point_transform(image, cardCoords)
# return the color matching card to the calling function
return card

# construct the argument parser and parse the arguments


ap = argparse.ArgumentParser()
ap.add_argument("-r", "--reference", required=True,
help="path to the input reference image")
ap.add_argument("-i", "--input", required=True,
help="path to the input image to apply color correction to")
args = vars(ap.parse_args())
# load the reference image and input images from disk
print("[INFO] loading images...")
ref = cv2.imread(args["reference"])
image = cv2.imread(args["input"])
# resize the reference and input images
ref = imutils.resize(ref, width=600)
image = imutils.resize(image, width=600)
# display the reference and input images to our screen
cv2.imshow("Reference", ref)
cv2.imshow("Input", image)
# find the color matching card in each image
print("[INFO] finding color matching cards...")
refCard = find_color_card(ref)
imageCard = find_color_card(image)
# if the color matching card is not found in either the reference
# image or the input image, gracefully exit
if refCard is None or imageCard is None:
print("[INFO] could not find color matching card in both images")
sys.exit(0)
# show the color matching card in the reference image and input image,
# respectively
cv2.imshow("Reference Color Card", refCard)
cv2.imshow("Input Color Card", imageCard)
# apply histogram matching from the color matching card in the
# reference image to the color matching card in the input image
print("[INFO] matching images...")
imageCard = exposure.match_histograms(imageCard, refCard, multichannel=True)
# show our input color matching card after histogram matching
cv2.imshow("Input Color Card After Matching", imageCard)
cv2.waitKey(0)

Left: reference image. Note the shade of teal placed in the center of the card. Right:
input image. The shade of teal is brighter than the reference image. Our goal is to apply
color matching/correction to resolve this discrepancy.

Left: Detecting the color matching card in the reference image. Middle: Extracting the
color card from the input image. Right: Output after applying color matching. Notice how
the shade of teal on the right more closely resembles the shade in the input image.
6. DETECTING LOW CONTRAST IMAGES
# import the necessary packages
from skimage.exposure import is_low_contrast
from imutils.paths import list_images
import argparse
import imutils
import cv2
# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--input", required=True, help="path to input directory of images")
ap.add_argument("-t", "--thresh", type=float, default=0.35,
help="threshold for low contrast")
args = vars(ap.parse_args())
# grab the paths to the input images
imagePaths = sorted(list(list_images(args["input"])))
# loop over the image paths
for (i, imagePath) in enumerate(imagePaths):
# load the input image from disk, resize it, and convert it to grayscale
print("[INFO] processing image {}/{}".format(i + 1,
len(imagePaths)))
image = cv2.imread(imagePath)
image = imutils.resize(image, width=450)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# blur the image slightly and perform edge detection
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(blurred, 30, 150)
# initialize the text and color to indicate that the input image
# is *not* low contrast
text = "Low contrast: No"
color = (0, 255, 0)
# check to see if the image is low contrast
if is_low_contrast(gray, fraction_threshold=args["thresh"]):
# update the text and color
text = "Low contrast: Yes"
color = (0, 0, 255)
# otherwise, the image is *not* low contrast, so we can continue processing it
else:
# find contours in the edge map and find the largest one, which we'll assume is the
# outline of our color correction card
cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
c = max(cnts, key=cv2.contourArea)
# draw the largest contour on the image
cv2.drawContours(image, [c], -1, (0, 255, 0), 2)
# draw the text on the output image
cv2.putText(image, text, (5, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.8,
color, 2)
# show the output image and edge map
cv2.imshow("Image", image)
cv2.imshow("Edge", edged)
cv2.waitKey(0)

You might also like