-
Notifications
You must be signed in to change notification settings - Fork 20
/
stereomatch_SSD.py
61 lines (49 loc) · 2.76 KB
/
stereomatch_SSD.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!/usr/bin/env python
# --------------------------------------------------------------------
# Simple sum of squared differences (SSD) stereo-matching using Numpy
# --------------------------------------------------------------------
# Copyright (c) 2016 David Christian
# Licensed under the MIT License
import numpy as np
from PIL import Image
def stereo_match(left_img, right_img, kernel, max_offset):
# Load in both images, assumed to be RGBA 8bit per channel images
left_img = Image.open(left_img).convert('L')
left = np.asarray(left_img)
right_img = Image.open(right_img).convert('L')
right = np.asarray(right_img)
w, h = left_img.size # assume that both images are same size
# Depth (or disparity) map
depth = np.zeros((w, h), np.uint8)
depth.shape = h, w
kernel_half = int(kernel / 2)
offset_adjust = 255 / max_offset # this is used to map depth map output to 0-255 range
for y in range(kernel_half, h - kernel_half):
print("\rProcessing.. %d%% complete"%(y / (h - kernel_half) * 100), end="", flush=True)
for x in range(kernel_half, w - kernel_half):
best_offset = 0
prev_ssd = 65534
for offset in range(max_offset):
ssd = 0
ssd_temp = 0
# v and u are the x,y of our local window search, used to ensure a good match
# because the squared differences of two pixels alone is not enough ot go on
for v in range(-kernel_half, kernel_half):
for u in range(-kernel_half, kernel_half):
# iteratively sum the sum of squared differences value for this block
# left[] and right[] are arrays of uint8, so converting them to int saves
# potential overflow
ssd_temp = int(left[y+v, x+u]) - int(right[y+v, (x+u) - offset])
ssd += ssd_temp * ssd_temp
# if this value is smaller than the previous ssd at this block
# then it's theoretically a closer match. Store this value against
# this block..
if ssd < prev_ssd:
prev_ssd = ssd
best_offset = offset
# set depth output for this x,y location to the best match
depth[y, x] = best_offset * offset_adjust
# Convert to PIL and save it
Image.fromarray(depth).save('depth.png')
if __name__ == '__main__':
stereo_match("view0.png", "view1.png", 6, 30) # 6x6 local search kernel, 30 pixel search range