mirror of
https://github.com/jlengrand/Tippy.git
synced 2026-03-10 08:51:16 +00:00
Adds histogram support to 3 channels images
compute_histogram support is available. hist2table support is available hist2image still to be performed. Function for 3c to 1c to be added quickly! Reported-by: Julien Lengrand-Lambert <julien@lengrand.fr> Signed-off-by: Julien Lengrand-Lambert <julien@lengrand.fr>
This commit is contained in:
@@ -23,12 +23,10 @@ import cv
|
||||
import tippy.statistics as st
|
||||
import tippy.display_operations as do
|
||||
|
||||
hist = st.Histogram()
|
||||
|
||||
img_name = "tippy/data/gnu.jpg"
|
||||
img = cv.LoadImage(img_name, cv.CV_LOAD_IMAGE_GRAYSCALE)
|
||||
hist.compute_histogram(img)
|
||||
img = cv.LoadImage(img_name, cv.CV_LOAD_IMAGE_COLOR)
|
||||
hist = st.Histogram(img)
|
||||
|
||||
hist_img = hist.hist2image()
|
||||
|
||||
do.display_single_image(hist_img, "Gray-Level histogram of the gnu image")
|
||||
do.display_single_image(hist_img[0], "Gray-Level histogram of the gnu image")
|
||||
|
||||
@@ -18,12 +18,13 @@ class Histogram():
|
||||
NOTE : Supports only 1 channel / 8 bits images for now.
|
||||
More should be added soon.
|
||||
"""
|
||||
def __init__(self):
|
||||
def __init__(self, img, bin_fact=cv.IPL_DEPTH_8U, min_range=0):
|
||||
self.cvhist = None
|
||||
self.min_range = 0
|
||||
self.depth = cv.IPL_DEPTH_8U
|
||||
self.nb_bins = 0
|
||||
self.channels = 0
|
||||
self.compute_histogram(img, bin_fact, min_range)
|
||||
|
||||
def compute_histogram(self, img, bin_fact=cv.IPL_DEPTH_8U, min_range=0):
|
||||
"""
|
||||
@@ -40,7 +41,7 @@ class Histogram():
|
||||
"""
|
||||
# TESTS
|
||||
try:
|
||||
cv.GetSize(img)
|
||||
dims = cv.GetSize(img)
|
||||
except TypeError:
|
||||
raise TypeError("(%s) img : IplImage expected!"
|
||||
% (sys._getframe().f_code.co_name))
|
||||
@@ -49,10 +50,9 @@ class Histogram():
|
||||
if not(img.depth == cv.IPL_DEPTH_8U):
|
||||
raise TypeError("(%s) 8U image expected!"
|
||||
% (sys._getframe().f_code.co_name))
|
||||
elif not(img.nChannels is 1):
|
||||
raise TypeError("(%s) 1C image expected!"
|
||||
% (sys._getframe().f_code.co_name))
|
||||
|
||||
if img.nChannels not in [1, 3]:
|
||||
raise ValueError("(%s) 1 or 3 channels image expected!"
|
||||
% (sys._getframe().f_code.co_name))
|
||||
# bin_fact test
|
||||
if (bin_fact <= 0 or ((bin_fact % 2) != 0)):
|
||||
raise ValueError("(%s) Positive odd integer expected!"
|
||||
@@ -71,15 +71,41 @@ class Histogram():
|
||||
self.depth = int(img.depth)
|
||||
max_range = pow(2, self.depth)
|
||||
self.ranges = [min_range, max_range]
|
||||
|
||||
|
||||
img_list = []
|
||||
# preparing images depending on nChannels
|
||||
if self.channels == 1:
|
||||
img_list = [img]
|
||||
elif self.channels == 3:
|
||||
# TODO: change this into function
|
||||
img_1 = cv.CreateImage(dims, cv.IPL_DEPTH_8U, 1)
|
||||
img_2 = cv.CreateImage(dims, cv.IPL_DEPTH_8U, 1)
|
||||
img_3 = cv.CreateImage(dims, cv.IPL_DEPTH_8U, 1)
|
||||
|
||||
cv.Split(img, img_1, img_2, img_3, None)
|
||||
img_list = [img_1, img_2, img_3]
|
||||
|
||||
self.cvhist = self._compute_1ch_histogram(img_list)
|
||||
|
||||
def _compute_1ch_histogram(self, img_list):
|
||||
"""
|
||||
DESIGNED FOR INTERNAL USE ONLY
|
||||
CAREFUL, NO VERIFICATIONS PERFORMED
|
||||
"""
|
||||
dims = [self.nb_bins]
|
||||
all_ranges = [self.ranges]
|
||||
|
||||
self.cvhist = cv.CreateHist( dims,
|
||||
cv.CV_HIST_ARRAY,
|
||||
all_ranges,
|
||||
uniform=1)
|
||||
cv.CalcHist([img], self.cvhist)
|
||||
hist_list = []
|
||||
for img in img_list:
|
||||
hist = cv.CreateHist( dims,
|
||||
cv.CV_HIST_ARRAY,
|
||||
all_ranges,
|
||||
uniform=1)
|
||||
cv.CalcHist([img], hist)
|
||||
|
||||
hist_list.append(hist)
|
||||
|
||||
return hist_list
|
||||
|
||||
def hist2table(self):
|
||||
"""
|
||||
@@ -94,9 +120,11 @@ class Histogram():
|
||||
% (sys._getframe().f_code.co_name))
|
||||
|
||||
histable = []
|
||||
for jj in range(self.nb_bins):
|
||||
histable.append(self.cvhist.bins[jj])
|
||||
|
||||
for ii in range(self.channels):
|
||||
hist_list = []
|
||||
for jj in range(self.nb_bins):
|
||||
hist_list.append(self.cvhist[ii].bins[jj])
|
||||
histable.append(hist_list)
|
||||
return histable
|
||||
|
||||
def hist2image(self, scale_x=3, scale_y=3, y_range=64):
|
||||
|
||||
@@ -17,7 +17,8 @@ class Test(unittest.TestCase):
|
||||
This method is called before each test
|
||||
"""
|
||||
self.img_1c = cv.LoadImage("data/tippy.jpg", cv.CV_LOAD_IMAGE_GRAYSCALE) # 1 channel image
|
||||
self.img_3c = cv.LoadImage("data/tippy.jpg", cv.CV_LOAD_IMAGE_COLOR) # 3 channel image
|
||||
self.img_3c = cv.LoadImage("data/tippy.jpg", cv.CV_LOAD_IMAGE_COLOR) # 3 channel image
|
||||
self.img_2c = cv.CreateImage((10, 10), cv.IPL_DEPTH_8U, 2) # fake 2 channels image
|
||||
self.img_16s = cv.CreateImage((15, 15), cv.IPL_DEPTH_16S, 1) # Non 8 bits image
|
||||
|
||||
self.val = 10 # non Image
|
||||
@@ -33,34 +34,35 @@ class Test(unittest.TestCase):
|
||||
#---
|
||||
## TESTS
|
||||
def test_compute_histogram(self):
|
||||
hist = st.Histogram()
|
||||
# testing input image
|
||||
self.assertRaises(TypeError, lambda:hist.compute_histogram(self.val) )
|
||||
self.assertRaises(TypeError, lambda:hist.compute_histogram(self.img_3c))
|
||||
|
||||
self.assertRaises(TypeError, lambda:st.Histogram(self.val) )
|
||||
self.assertRaises(TypeError, lambda:st.Histogram(self.img_16s) )
|
||||
self.assertRaises(ValueError, lambda:st.Histogram(self.img_2c) )
|
||||
# testing bin_fact
|
||||
self.assertRaises(ValueError,
|
||||
lambda: hist.compute_histogram(self.img_1c, self.neg_val))
|
||||
lambda: st.Histogram(self.img_1c, self.neg_val))
|
||||
self.assertRaises(TypeError,
|
||||
lambda: hist.compute_histogram(self.img_1c, self.string))
|
||||
lambda: st.Histogram(self.img_1c, self.string))
|
||||
|
||||
# testing min_range. It can be either negative or even.
|
||||
self.assertRaises(TypeError,
|
||||
lambda: hist.compute_histogram(self.img_1c, self.val, self.string))
|
||||
lambda: st.Histogram(self.img_1c, self.val, self.string))
|
||||
|
||||
# testing output
|
||||
hist_1c = st.Histogram(self.img_1c)
|
||||
self.assertEquals(self.img_1c.nChannels, hist_1c.channels)
|
||||
hist_3c = st.Histogram(self.img_3c)
|
||||
self.assertEquals(self.img_3c.nChannels, hist_3c.channels)
|
||||
|
||||
def test_hist2table(self):
|
||||
hist = st.Histogram()
|
||||
# testing input histogram
|
||||
self.assertRaises(TypeError, lambda: hist.hist2table(self.val))
|
||||
# testing output size
|
||||
hist.compute_histogram(self.img_1c)
|
||||
hist = st.Histogram(self.img_3c)
|
||||
histable = hist.hist2table()
|
||||
self.assertEqual(256, len(histable))
|
||||
self.assertEqual(3, len(histable))
|
||||
self.assertEqual(256, len(histable[0]))
|
||||
|
||||
def test_hist2image(self):
|
||||
hist = st.Histogram()
|
||||
# testing input histogram
|
||||
self.assertRaises(TypeError, lambda: hist.hist2image(self.val))
|
||||
def test_hist2image(self):
|
||||
hist = st.Histogram(self.img_1c)
|
||||
# testing scale inputs
|
||||
self.assertRaises(TypeError,
|
||||
lambda: hist.hist2image(hist, self.string))
|
||||
|
||||
Reference in New Issue
Block a user