Skip to content

Instantly share code, notes, and snippets.

@macrat
Last active October 31, 2016 08:34
Show Gist options
  • Save macrat/7a7e96e52e3a6d44abf60f6ab200e945 to your computer and use it in GitHub Desktop.
Save macrat/7a7e96e52e3a6d44abf60f6ab200e945 to your computer and use it in GitHub Desktop.
黒板とかホワイトボードに投影した映像をカメラで映して何かしようとした残骸。
import time
import cv2
import numpy
SCREEN_SIZE = (1024, 768)
cam = cv2.VideoCapture(0)
cv2.namedWindow('screen', 0x10)
def take_photo():
return cv2.resize(cam.read()[1], (1024, 768))
def take_clear_photo():
img = numpy.array(take_photo(), numpy.uint64)
for i in range(11):
time.sleep(0.01)
img += take_photo()
return numpy.array(img/12, numpy.uint8)
def take_gray_photo():
return cv2.cvtColor(take_clear_photo(), cv2.COLOR_BGR2GRAY)
def find_max_pos(img):
max_score = 0
max_pos = (0, 0)
for y in range(0, img.shape[0], 8):
for x in range(0, img.shape[1], 8):
score = img[y:y+8, x:x+8].sum()
if score > max_score:
max_score = score
max_pos = (x + 4, y + 4)
return max_pos
def find_diff_pos(a, b):
return find_max_pos(((cv2.absdiff(a, b) > 128) * 255).astype(numpy.uint8))
def display(img, name='screen'):
cv2.imshow(name, img)
cv2.waitKey(1)
def find_corner():
poses = []
for x, y in ((0, 0),
(SCREEN_SIZE[0], 0),
SCREEN_SIZE,
(0, SCREEN_SIZE[1])):
img = numpy.zeros(SCREEN_SIZE[::-1], numpy.uint8)
display(img)
time.sleep(0.1)
bg = take_gray_photo()
cv2.circle(img, (x, y), 32, 255, -1)
display(img)
time.sleep(0.1)
img = take_gray_photo()
poses.append(find_diff_pos(bg, img))
corners = ((0, 0),
(img.shape[1], 0),
(img.shape[1], img.shape[0]),
(0, img.shape[0]))
m = cv2.getPerspectiveTransform(numpy.array(poses, numpy.float32),
numpy.array(corners, numpy.float32))
return poses, m
class ContourDetector:
def __init__(self, initial_img):
self.lowpass = initial_img
def update(self, img):
self.lowpass = (self.lowpass*0.9 + img*0.1).astype(numpy.uint8)
hsv = cv2.GaussianBlur(self.lowpass, (9, 9), 10)
hsv = cv2.cvtColor(hsv, cv2.COLOR_BGR2HSV)
filtered = (
(100 < hsv[:,:,0])
* (hsv[:,:,0] < 110)
* 255
).astype(numpy.uint8)
binary = cv2.GaussianBlur(filtered, (9, 9), 10)
display(binary, name='binary')
binary = cv2.threshold(binary, 128, 255, cv2.THRESH_BINARY)[1]
cnts = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[1]
lines = img.copy()
for c in cnts:
arclen = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.02*arclen, True)
cv2.drawContours(lines, [approx], -1, (0, 255, 0), -1)
return cnts, lines
if __name__ == '__main__':
corner, m = find_corner()
cd = ContourDetector(take_photo())
while True:
img = take_photo()
warped = cv2.warpPerspective(img, m, (img.shape[1], img.shape[0]))
display(cd.update(warped)[1])
for c in corner:
cv2.circle(img, c, 4, (0, 255, 0), -1)
cv2.circle(img, c, 6, (0, 255, 0), 1)
display(img, name='monitor')
k = cv2.waitKey(15)
if k == 27:
break
elif k == ord(' '):
corner, m = find_corner()
import cv2
import numpy
cam = cv2.VideoCapture(0)
lowpass = cam.read()[1]
while cv2.waitKey(15) < 0:
ok, img = cam.read()
if not ok:
break
lowpass = numpy.array(lowpass*0.9 + img*0.1, numpy.uint8)
hsv = cv2.GaussianBlur(lowpass, (9, 9), 10)
hsv = cv2.cvtColor(hsv, cv2.COLOR_BGR2HSV)
filtered = numpy.array((100 < hsv[:,:,0]) * (hsv[:,:,0] < 110) * 255, numpy.uint8)
binary = cv2.GaussianBlur(filtered, (9, 9), 10)
binary = cv2.threshold(binary, 128, 255, cv2.THRESH_BINARY)[1]
cv2.imshow('binary', binary)
cnts = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[1]
lines = img.copy()
for c in cnts:
arclen = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.02*arclen, True)
cv2.drawContours(lines, [approx], -1, (0, 255, 0), -1)
cv2.imshow('lines', lines)
cv2.imshow('filtered', filtered)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment