Ask Your Question
0

How to detect semi transparent logo location on video?

asked 2013-03-24 09:37:16 -0600

alex1306 gravatar image

I make python script which auto detect stationary object on video (to simplify the idea - let it be a logo). I don't know logo location, because I can't see video. I start script in console. The idea of script - auto detection, not manual work. But I know that logo is on all video frames, and it located as usual in one of the coner.

I have small test videos:

https://dl.dropbox.com/u/100403694/1.mp4

https://dl.dropbox.com/u/100403694/2.mp4

https://dl.dropbox.com/u/100403694/3.mp4

https://dl.dropbox.com/u/100403694/4.mp4

All tests seems to be done except 2.mp4 Script can't detect logo on video 2.mp4

This is my script. Usage script.py 2.mp4

#!/usr/bin/env python
# -*- coding= utf-8 -*-

import sys
import cv2
import numpy as np
from time import clock

tracked_contours = []

class Contour():
    def __init__(self, contour):
        self.data = get_contour_data(contour)
        self.pixel_error = 5
        self.score = 0

    def __eq__(self, other):
        for i in range(len(self.data)):
            if abs(self.data[i]-other.data[i]) > self.pixel_error:
                return False
        return True

def get_contour_data(contour):
    xx = np.array([ a[0][0] for a in contour ])
    yy = np.array([ a[0][1] for a in contour ])
    return [xx.min(), yy.min(), xx.max(), yy.max()]

def check_contours(contours, count, img):
    for tracked_contour in tracked_contours:
        if count % 2 == 0:
            tracked_contour.score -= 1

        if tracked_contour.score < 0:
            tracked_contours.remove(tracked_contour)

    for contour in contours:
        c = Contour(contour)
        if c in tracked_contours:
            i = tracked_contours.index(c)
            tracked_contours[i].score += 1
            cv2.rectangle(img, (tracked_contours[i].data[0], \
                tracked_contours[i].data[1]), (tracked_contours[i].data[2], \
                tracked_contours[i].data[3]), (tracked_contours[i].score*10, tracked_contours[i].score*5, tracked_contours[i].score), tracked_contours[i].score)
            if tracked_contours[i].score > 40:
                return True, c
        else: tracked_contours.append(c)

    return False, None

def drawContours(contours, img):
    for contour in contours:
        data = get_contour_data(contour)
        cv2.rectangle(img, (data[0], data[1]), (data[2], data[3]), (255,0,0))

def detect(file_name):
    c = cv2.VideoCapture(file_name)
    _,f = c.read()
    f = cv2.cvtColor(f, cv2.COLOR_BGR2GRAY)

    avg = np.float32(f)

    cv2.namedWindow("img")
    cv2.namedWindow("grey")
    cv2.namedWindow("avg")

    t = 0
    count = 0

    while(1):
        if t % 5 != 0:
            _,f = c.read()
            if f == None:
                exit(1)
            t+=1
            continue
        count += 1
        t += 1

        _,f = c.read()

        if f == None:
            exit(1)

        cv2.imshow('img',f)

        f = np.float32(cv2.cvtColor(f, cv2.COLOR_BGR2GRAY))

        cv2.accumulateWeighted(f, avg, 0.005)

        res = cv2.convertScaleAbs(avg)

        cv2.imshow('grey',res)

        thresh, res = cv2.threshold(res, 200, 255, cv2.THRESH_BINARY)
        kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(40,40))
        mat = cv2.dilate(res,kernel)

        contours, hierarchy = cv2.findContours(mat,cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_L1)
        res = cv2.cvtColor(res, cv2.COLOR_GRAY2BGR)
        a,b = check_contours(contours, count, res)

        if a == True:
            cv2.rectangle(res, (b.data[0], b.data[1]), (b.data[2], b.data[3]), (0,255,0), 5)
            cv2.imshow('avg',res)
            k = cv2.waitKey(5000 ...
(more)
edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
1

answered 2013-03-25 08:07:13 -0600

Did you try a simple background subtraction, with history? The logo should be in the area, where pixels are less changing. With your prior, you can only get background subtraction in the 4 corners where it is supposed to be.

For the subtraction, I think you will have better results with absdiff than with Mixture of Gaussian subtraction. After finding the logo in the first video, you can either used SIFT/SURF or template matching for others video to directly detect the logo, maybe also the corner position of first video.

edit flag offensive delete link more
0

answered 2013-03-24 16:25:53 -0600

Just looking at your code i notice you're trying an approach based on contour segmentation. However, if you actually know the object you are looking for, I would suggest using feature matching approaches like SURF, SIFT or ORB.

Information can be found here on these links:

Those can actually detect feature points in new frames that are common to the feature points in the object. You will get way better detection results.

edit flag offensive delete link more

Comments

2

Or, you can used Template Matching, if you logo is static (no rotation or scale variation). http://docs.opencv.org/modules/imgproc/doc/object_detection.html?highlight=matchtemplate#cv2.matchTemplate

Mathieu Barnachon gravatar imageMathieu Barnachon ( 2013-03-25 03:38:03 -0600 )edit

I don't know how logo looks like before script start. Automate detection unchanged area on video without any templates.

alex1306 gravatar imagealex1306 ( 2013-03-25 07:43:28 -0600 )edit
1

Then some more preprocessing steps you need to apply are

  • detect image regions that are still : for example subtract following frames

  • define a minimum size inside that mask for a region that looks interesting to you

  • once that region is found, apply SURF, SIFT, ORB

  • look in following frames if it can be retrieved again

StevenPuttemans gravatar imageStevenPuttemans ( 2013-03-25 08:19:15 -0600 )edit
1

We are agree ;)

Mathieu Barnachon gravatar imageMathieu Barnachon ( 2013-03-25 08:32:45 -0600 )edit

Question Tools

Stats

Asked: 2013-03-24 09:37:16 -0600

Seen: 2,858 times

Last updated: Mar 25 '13