mirror of
https://github.com/jlengrand/image_processing.git
synced 2026-03-10 08:11:18 +00:00
228 lines
6.8 KiB
Python
228 lines
6.8 KiB
Python
'''
|
|
Created on 25 mai 2012
|
|
|
|
@author: jlengrand
|
|
'''
|
|
import sys
|
|
|
|
import cv
|
|
|
|
# ---- Useful functions ----
|
|
|
|
def init_video(video_file):
|
|
"""
|
|
Given the name of the video, prepares the stream and checks that everything works as attended
|
|
"""
|
|
capture = cv.CaptureFromFile(video_file)
|
|
|
|
nFrames = int( cv.GetCaptureProperty( capture, cv.CV_CAP_PROP_FRAME_COUNT ) )
|
|
fps = cv.GetCaptureProperty( capture, cv.CV_CAP_PROP_FPS )
|
|
if fps != 0:
|
|
waitPerFrameInMillisec = int( 1/fps * 1000/1 )
|
|
|
|
print 'Num. Frames = ', nFrames
|
|
print 'Frame Rate = ', fps, ' frames per sec'
|
|
|
|
print '----'
|
|
|
|
return capture
|
|
else:
|
|
return None
|
|
|
|
def display_img(img, delay=1000):
|
|
"""
|
|
One liner that displays the given image on screen
|
|
"""
|
|
cv.NamedWindow("Vid", cv.CV_WINDOW_AUTOSIZE)
|
|
cv.ShowImage("Vid", img)
|
|
cv.WaitKey(delay)
|
|
|
|
def display_video(my_video, frame_inc=100, delay=100):
|
|
"""
|
|
Displays frames of the video in a dumb way.
|
|
Used to see if everything is working fine
|
|
my_video = cvCapture object
|
|
frame_inc = Nmber of increments between each frame displayed
|
|
delay = time delay between each image
|
|
"""
|
|
cpt = 0
|
|
img = cv.QueryFrame(my_video)
|
|
|
|
if img != None:
|
|
cv.NamedWindow("Vid", cv.CV_WINDOW_AUTOSIZE)
|
|
else:
|
|
return None
|
|
|
|
nFrames = int( cv.GetCaptureProperty( my_video, cv.CV_CAP_PROP_FRAME_COUNT ) )
|
|
while cpt < nFrames:
|
|
for ii in range(frame_inc):
|
|
img = cv.QueryFrame(my_video)
|
|
cpt + 1
|
|
|
|
cv.ShowImage("Vid", img)
|
|
cv.WaitKey(delay)
|
|
|
|
def grab_images(video_file, frame_inc=100, delay = 100):
|
|
"""
|
|
Walks through the entire video and save image for each increment
|
|
"""
|
|
my_video = init_video(video_file)
|
|
if my_video != None:
|
|
# Display the video and save evry increment frames
|
|
cpt = 0
|
|
img = cv.QueryFrame(my_video)
|
|
|
|
if img != None:
|
|
cv.NamedWindow("Vid", cv.CV_WINDOW_AUTOSIZE)
|
|
else:
|
|
return None
|
|
|
|
nFrames = int( cv.GetCaptureProperty( my_video, cv.CV_CAP_PROP_FRAME_COUNT ) )
|
|
while cpt < nFrames:
|
|
for ii in range(frame_inc):
|
|
img = cv.QueryFrame(my_video)
|
|
cpt += 1
|
|
|
|
cv.ShowImage("Vid", img)
|
|
out_name = "data/output/" + str(cpt) + ".jpg"
|
|
cv.SaveImage(out_name, img)
|
|
print out_name, str(nFrames)
|
|
cv.WaitKey(delay)
|
|
else:
|
|
return None
|
|
|
|
def to_gray(img):
|
|
"""
|
|
Converts the input in grey levels
|
|
Returns a one channel image
|
|
"""
|
|
grey_img = cv.CreateImage(cv.GetSize(img), img.depth, 1)
|
|
cv.CvtColor(img, grey_img, cv.CV_RGB2GRAY )
|
|
|
|
return grey_img
|
|
|
|
def grey_histogram(img, nBins=64):
|
|
"""
|
|
Returns a one dimension histogram for the given image
|
|
The image is expected to have one channel, 8 bits depth
|
|
nBins can be defined between 1 and 255
|
|
"""
|
|
hist_size = [nBins]
|
|
h_ranges = [0, 255]
|
|
hist = cv.CreateHist(hist_size , cv.CV_HIST_ARRAY, [[0, 255]], 1)
|
|
cv.CalcHist([img], hist)
|
|
|
|
return hist
|
|
|
|
def extract_bright(grey_img, histogram=False):
|
|
"""
|
|
Extracts brightest part of the image.
|
|
Expected to be the LEDs (provided that there is a dark background)
|
|
Returns a Thresholded image
|
|
histgram defines if we use the hist calculation to find the best margin
|
|
"""
|
|
## Searches for image maximum (brightest pixel)
|
|
# We expect the LEDs to be brighter than the rest of the image
|
|
[minVal, maxVal, minLoc, maxLoc] = cv.MinMaxLoc(grey_img)
|
|
print "Brightest pixel val is %d" %(maxVal)
|
|
|
|
#We retrieve only the brightest part of the image
|
|
# Here is use a fixed margin (80%), but you can use hist to enhance this one
|
|
if 0:
|
|
## Histogram may be used to wisely define the margin
|
|
# We expect a huge spike corresponding to the mean of the background
|
|
# and another smaller spike of bright values (the LEDs)
|
|
hist = grey_histogram(img, nBins=64)
|
|
[hminValue, hmaxValue, hminIdx, hmaxIdx] = cv.GetMinMaxHistValue(hist)
|
|
margin = 0# statistics to be calculated using hist data
|
|
else:
|
|
margin = 0.8
|
|
|
|
thresh = int( maxVal * margin) # in pix value to be extracted
|
|
print "Threshold is defined as %d" %(thresh)
|
|
|
|
thresh_img = cv.CreateImage(cv.GetSize(img), img.depth, 1)
|
|
cv.Threshold(grey_img, thresh_img , thresh, 255, cv.CV_THRESH_BINARY)
|
|
|
|
return thresh_img
|
|
|
|
def find_leds(thresh_img):
|
|
"""
|
|
Given a binary image showing the brightest pixels in an image,
|
|
returns a result image, displaying found leds in a rectangle
|
|
"""
|
|
contours = cv.FindContours(thresh_img,
|
|
cv.CreateMemStorage(),
|
|
mode=cv.CV_RETR_EXTERNAL ,
|
|
method=cv.CV_CHAIN_APPROX_NONE ,
|
|
offset=(0, 0))
|
|
|
|
regions = []
|
|
while contours:
|
|
pts = [ pt for pt in contours ]
|
|
x, y = zip(*pts)
|
|
min_x, min_y = min(x), min(y)
|
|
width, height = max(x) - min_x + 1, max(y) - min_y + 1
|
|
regions.append((min_x, min_y, width, height))
|
|
contours = contours.h_next()
|
|
|
|
out_img = cv.CreateImage(cv.GetSize(grey_img), 8, 3)
|
|
for x,y,width,height in regions:
|
|
pt1 = x,y
|
|
pt2 = x+width,y+height
|
|
color = (0,0,255,0)
|
|
cv.Rectangle(out_img, pt1, pt2, color, 2)
|
|
|
|
return out_img, regions
|
|
|
|
def leds_positions(regions):
|
|
"""
|
|
Function using the regions in input to calculate the position of found leds
|
|
"""
|
|
centers = []
|
|
for x, y, width, height in regions:
|
|
centers.append( [x+ (width / 2),y + (height / 2)])
|
|
|
|
return centers
|
|
|
|
|
|
if __name__ == '__main__':
|
|
video_file = "data/MusicLEDBox.avi"
|
|
|
|
if 0:
|
|
# do once once, create some images out of the video
|
|
grab_images(video_file, frame_inc=100, delay = 100)
|
|
|
|
|
|
img = cv.LoadImage("data/output/600.jpg")
|
|
if img != None:
|
|
# Displays the image I ll be working with
|
|
display_img(img, delay = 100)
|
|
else:
|
|
print "IMG not found !"
|
|
sys.exit(0)
|
|
|
|
####
|
|
# Starts image processing here
|
|
####
|
|
# Turns to one channel image
|
|
grey_img = to_gray(img)
|
|
display_img(grey_img, 1000)
|
|
# Detect brightest point in image :
|
|
thresh_img = extract_bright(grey_img)
|
|
display_img(thresh_img, delay = 1000)
|
|
|
|
# We want to extract the elements left, and count their number
|
|
led_img, regions = find_leds(thresh_img)
|
|
display_img(led_img, delay=1000)
|
|
|
|
centers = leds_positions(regions)
|
|
|
|
print "Total number of Leds found : %d !" %(len(centers))
|
|
print "###"
|
|
print "Led positions :"
|
|
for c in centers:
|
|
print "x : %d; y : %d" %(c[0], c[1])
|
|
print "###"
|
|
|