Skip to content

Commit

Permalink
new preprocessor commit 1
Browse files Browse the repository at this point in the history
  • Loading branch information
thoklei committed Jul 16, 2019
1 parent be5f11c commit 776a811
Show file tree
Hide file tree
Showing 13 changed files with 1,956 additions and 73 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
*.cb
*.cb2
.*.lb

*.jpg
## Intermediate documents:
*.dvi
*.xdv
Expand Down
2 changes: 1 addition & 1 deletion code/notebooks/data_augmentation_logic.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.6"
"version": "3.6.5"
}
},
"nbformat": 4,
Expand Down
2 changes: 1 addition & 1 deletion code/notebooks/manual_feature_extractor.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.6"
"version": "3.6.5"
}
},
"nbformat": 4,
Expand Down
1,806 changes: 1,806 additions & 0 deletions code/notebooks/verify_manual_extraction.ipynb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion code/notebooks/width_extraction.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.6"
"version": "3.6.5"
}
},
"nbformat": 4,
Expand Down
173 changes: 104 additions & 69 deletions code/preprocessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from scipy.ndimage.morphology import binary_hit_or_miss, binary_opening, binary_closing, binary_dilation
from scipy.ndimage import label, find_objects
from sklearn.decomposition.pca import PCA

from skimage.measure import label, regionprops

# @Thomas, why were those nested?
def binarize_asparagus_img(img):
Expand All @@ -23,28 +23,8 @@ def blue_delta(img):
blue = blue_delta(img) > 25
return np.logical_and(white, np.invert(blue))


# @Thomas, why do you use dilation after the opening?
# I commented it out for the proprocessing for the feature extraction
# if we still need it at another point we have to change this back
# TODO: clean comments
def filter_mask_img(img):
"""Opening on the binarized image.
Args:
img: image
Returns:
rotated_img: image after opening
"""
img = binary_opening(img, structure=np.ones((21, 21))) # 21,21
# sometimes, it cuts the heads off, so mostly vertical dilation
# img = binary_dilation(img, np.ones((60, 20)))
# unnecessary with new approach
# img = binary_closing(img, structure=np.ones((35,35))) # 45,45
return img


# Michaels function - might be redundant with Thomas' proprocessor function
def cut_background(img, background_max_hue, background_min_hue, background_brightness):
def cut_background(img, background_min_hue, background_max_hue, background_brightness):
""" Initiates masking in the hsv space.
Cuts out background with specific hue values.
Expand All @@ -60,17 +40,16 @@ def cut_background(img, background_max_hue, background_min_hue, background_brigh
"""

# Open Image
raw = img
raw = np.array(img)
# remove alpha-channel (only if its RGBA)
raw = raw[:,:,0:3]
# transform to HSV color space
hsv = matplotlib.colors.rgb_to_hsv(raw)

# Mask all blue hues (background)
mask = np.logical_and(hsv[:,:,0] > background_min_hue , hsv[:,:,0] < background_max_hue)
# Mask out values that are not bright enough
mask = np.logical_or(hsv[:,:,2]< background_brightness, mask)

# Mask out values that are not bright enough
mask = np.logical_or(hsv[:,:,2] < background_brightness, mask)
#Use binary hit and miss to remove potentially remaining isolated pixels:
m = np.logical_not(mask)

Expand All @@ -87,7 +66,7 @@ def cut_background(img, background_max_hue, background_min_hue, background_brigh
raw[:,:,2][mask] = 0


return raw
return mask, raw

def verticalize_img(img):
"""Rotate an image based on its principal axis, makes it upright.
Expand All @@ -108,6 +87,57 @@ def verticalize_img(img):
rotated_img = rotate(img, angle/np.pi*180+90)
return rotated_img

def mask_img(img):
"""
Finds asparagus in an image and returns a mask that is 1 for every pixel which belongs
to an asparagus piece and 0 everywhere else.
img = the image after running segmentation based on color
returns: mask as described above
"""
img = np.array(img)

def binarize(img, thres):
res = np.sum(img,axis=2) > thres
return res.astype(int)

bin_img = binarize(img, 10)

def find_largest_region(binary_img):
"""
Finds the largest continuous region in a binary image
(which hopefully is the asparagus piece)
binary_img = a binary image with patches of different sizes
returns: essentially a mask
"""
labeled_img = label(bin_img)
props = regionprops(labeled_img)
maxi = 0
maxval = 0
for i, prop in enumerate(props):
if prop.area > maxval:
maxi = i
maxval = prop.area

proppy = props[maxi]
coords = proppy.coords # 2d np array
empty = np.zeros(bin_img.shape)
for i in range(len(coords)):
empty[coords[i,0], coords[i,1]] = 1
return empty

# find largest region, open the image, and find the largest region
# once again, because the opening might just have created a small
# "island" instead of completely removing the noise
empty = find_largest_region(bin_img)
empty = binary_opening(empty, structure=np.ones((21,21)))
empty = find_largest_region(empty)

return empty

def preprocessor(img_dir, target_dir, show=True, save=False, debug=True, time_constraint=None, max_width = 250, max_height = 1200):
""" Walks over a directory full of images, detects asparagus in those images, extracts them with minimal bounding box
into an image of shape height x width and stores that image in target dir with a simple name.
Expand Down Expand Up @@ -139,8 +169,7 @@ def preprocessor(img_dir, target_dir, show=True, save=False, debug=True, time_co
idx = int(idx) + 1

for subdir, dirs, files in os.walk(img_dir):
files = sorted([f for f in files if not f[0]
== '.' and f[-4:] == '.bmp'])
files = sorted([f for f in files if not f[0] == '.' and f[-4:] == '.bmp'])
for file in files:
# print(os.path.join(subdir, file))
if((not ready) and current == file):
Expand All @@ -155,8 +184,7 @@ def preprocessor(img_dir, target_dir, show=True, save=False, debug=True, time_co
# gathering metadata
splits = file.split("-")
date = splits[1] # like 190411
batch_number, photo_number = splits[3].split(
"_") # like [874][F01.bmp]
batch_number, photo_number = splits[3].split("_") # like [874][F01.bmp]
photo_number = int(photo_number.split(".")[0][2:])
if(debug):
print("Date: {}".format(date))
Expand All @@ -179,56 +207,27 @@ def preprocessor(img_dir, target_dir, show=True, save=False, debug=True, time_co
plt.show()

# transform to binary (still just black and white)
binary = binarize_asparagus_img(subimg)

mask, color_seg_result = cut_background(subimg, 0.4, 0.8, 50)#binarize_asparagus_img(subimg)
# create mask, i.e.: Where is asparagus?
mask = filter_mask_img(binary)
#mask = filter_mask_img(binary)

if(debug):
plt.figure(figsize=(20, 20))
plt.imshow(mask)
plt.show()

# assign a label to each piece of asparagus
labeled_mask, num_features = label(mask)

#labeled_mask, num_features = label(mask)
mask = mask_img(color_seg_result)
# turn our mask into a color mask
cmask = np.stack([mask, mask, mask], axis=2)

# mask the image
masked = np.where(cmask, subimg, np.ones(
subimg.shape, dtype=np.uint8))

# find bounding box around every object, pieces = list of tuples, which are corners of bb:
# pieces[0] contains (x1,x2,None), (y1,y2,None) where x1y1 is the upper left coordinate and x2y2 the lower right
pieces = find_objects(labeled_mask)

for box in pieces:

hs, ws = box
delta_h = hs.stop - hs.start
delta_w = ws.stop - ws.start

# if the segment is too small, it was probably a light reflex
if(delta_w < 20 or delta_h < 300):
print("artifact discovered in {}".format(file))
else:
# patch is asparagus, extract to new image and add some padding
new_img = masked[hs.start:hs.stop,
ws.start:ws.stop, :]
lr = max_width - delta_w
ud = max_height - delta_h
new_img = np.pad(new_img, ((int(np.floor(ud/2)), int(np.ceil(ud/2))),
(int(np.floor(lr/2)),
int(np.ceil(lr/2))),
(0, 0)), "constant", constant_values=0)
if(show):
plt.figure(figsize=(15, 15))
plt.imshow(new_img)
plt.show()
if(save):
plt.imsave(os.path.join(target_dir, str(
idx)+"_"+str(photo_number)+".jpg"), new_img)
masked = np.where(cmask, subimg, np.ones(subimg.shape, dtype=np.uint8))

if(save):
plt.imsave(os.path.join(target_dir, str(
idx)+"_"+str(photo_number)+".jpg"), masked)

if(photo_number == 2):
progress.truncate(0)
Expand All @@ -237,4 +236,40 @@ def preprocessor(img_dir, target_dir, show=True, save=False, debug=True, time_co
idx += 1


if __name__ == "__main__":

from pathlib import Path



img_dir = "../images/raw_data/"
target_dir = "../images/test/"
target_dir_path = Path(target_dir)
if not target_dir_path.is_dir():
os.makedirs(target_dir_path)
if not Path(os.path.join(target_dir, "names.csv")).is_file():
open(os.path.join(target_dir, "names.csv"), 'a').close()
if not Path(os.path.join(img_dir, "progress.txt")).is_file():
open(os.path.join(img_dir, "progress.txt"), 'a').close()

try:
with open(os.path.join(img_dir, "progress.txt")) as file:
pass
except IOError:
file = open(os.path.join(img_dir, "progress.txt"), "w")
file.close()

try:
with open(os.path.join(target_dir, "names.csv")) as file:
pass
except IOError:
file = open(os.path.join(target_dir, "names.csv"), "a")
file.close()

avg_width = 160
avg_height = 1050

max_width = 250
max_height = 1200

preprocessor(img_dir, target_dir, show=False, save=True, debug=False)
Binary file added images/raw_data/progress.txt
Binary file not shown.
1 change: 1 addition & 0 deletions images/rust_test/names.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
G01-190609-104546-311_F02.bmp,0
Binary file not shown.
Binary file not shown.
Binary file not shown.
1 change: 1 addition & 0 deletions images/rust_test_raw/progress.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
G01-190609-104546-311_F02.bmp#0
40 changes: 40 additions & 0 deletions images/test/names.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
G01-190411-092055-873_F02.bmp,0
G01-190411-092055-874_F02.bmp,1
G01-190411-092055-875_F02.bmp,2
G01-190411-092056-876_F02.bmp,3
G01-190411-092056-877_F02.bmp,4
G01-190411-092058-887_F02.bmp,5
G01-190411-092058-888_F02.bmp,6
G01-190411-092059-890_F02.bmp,7
G01-190411-092059-891_F02.bmp,8
G01-190411-092059-892_F02.bmp,9
G01-190411-092100-893_F02.bmp,10
G01-190411-092100-894_F02.bmp,11
G01-190411-092122-988_F02.bmp,12
G01-190411-092123-989_F02.bmp,13
G01-190411-092123-990_F02.bmp,14
G01-190411-092123-991_F02.bmp,15
G01-190411-092124-995_F02.bmp,16
G01-190411-092125-998_F02.bmp,17
G01-190411-092743-578_F02.bmp,18
G01-190411-092743-579_F02.bmp,19
G01-190411-092744-583_F02.bmp,20
G01-190411-092745-586_F02.bmp,21
G01-190411-092745-588_F02.bmp,22
G01-190411-092746-590_F02.bmp,23
G01-190411-092747-594_F02.bmp,24
G01-190411-092748-602_F02.bmp,25
G01-190411-092751-614_F02.bmp,26
G01-190411-092752-616_F02.bmp,27
G01-190411-092753-619_F02.bmp,28
G01-190411-092753-621_F02.bmp,29
G01-190411-092758-642_F02.bmp,30
G01-190411-092759-645_F02.bmp,31
G01-190411-092759-646_F02.bmp,32
G01-190411-092759-647_F02.bmp,33
G01-190411-092800-649_F02.bmp,34
G01-190411-092801-654_F02.bmp,35
G01-190411-092801-655_F02.bmp,36
G01-190411-092801-656_F02.bmp,37
G01-190411-092802-658_F02.bmp,38
G01-190411-092806-675_F02.bmp,39

0 comments on commit 776a811

Please sign in to comment.