In [ ]:
import os
import random as rnd
import numpy as np
import pandas as pd
import peakutils
import cv2 as cv
from matplotlib import pyplot as plt
In [ ]:
%matplotlib notebook
In [ ]:
def add_images(dirname, offset=np.array([0, 0]), macrostep=np.array([0, 0]), step=np.array([0, 0]),\
infield_shifts=np.array([np.array([0, 0]), np.array([0, 0])]), annotation=None,\
multifields=True):
full_df = pd.DataFrame()
for i in os.listdir(dirname):
path = os.path.join(dirname, i)
if os.path.isfile(path):
parts = i.split('.')
if parts[-1] not in image_formats:
continue
name = ".".join(parts[0:-1]).split('_')
if len(name) >= 3 and not multifields:
if name[-3][:-1] != "f" and name[-3][:-1] != "F" and name[-3][:-1] != "field":
print("Supposedly auxillary image", i, "was not inserted")
continue
field = int(name[-3][-1])
shift = macrostep * np.array([(field - 1) % 2, (field - 1) // 2])
infield_shift = infield_shift[0]
elif len(name) >= 4 and multifields:
if name[-4][:-1] != "f" and name[-4][:-1] != "F" and name[-4][:-1] != "field":
print("Supposedly auxillary image", i, "was not inserted")
continue
field = int(name[-4][-1])
infield = name[-3]
shift = macrostep * np.array([(field-1) % 2, (field-1) // 2])
if infield == 'r':
infield_shift = infield_shifts[1]
elif infield == 'l':
infield_shift = infield_shifts[0]
else:
print("Wrong filename. Image", i, "was not inserted")
continue
else:
print("Wrong filename. Image", i, "was not inserted")
continue
p0 = offset + shift + infield_shift + np.array([int(name[-2])-1, int(name[-1])-1]) * step
sup_path = os.path.join(dirname, '_'.join(name) + '_sup.' + parts[-1])
if not os.path.isfile(sup_path):
sup_path = None
df = addpic(path, sup_path, p0, step, annotation)
if df is None:
print("Cannot find 4 crosses in", i)
continue
full_df = full_df.append(df)
full_df.to_csv(os.path.join(dirname, "info.csv"), header=None, index=False)
return full_df
def add_images_QDEV(dirname, macrooffset=np.array([360, 360]), offset=np.array([10, 12]),\
macrostep=np.array([600, 600]), step=np.array([120, 120]),\
ministep=np.array([25, 16]), annotation=None, threshold='Adaptive'):
full_df = pd.DataFrame()
for i in os.listdir(dirname):
path = os.path.join(dirname, i)
if os.path.isfile(path):
parts = i.split('.')
if parts[-1] not in image_formats:
continue
name = ".".join(parts[0:-1]).split('_')
if len(name) >= 6:
if name[-5][0] != "f" and name[-5][0] != "F" and name[-5][:-1] != "field":
print("Supposedly auxillary image", i, "was not inserted")
continue
field = int(name[-5][1:])
shift = macrooffset + macrostep*np.array([(field-1) % 4, (field-1) // 4])
shift += step*np.array([int(name[-4])-1, int(name[-3])-1])
p0 = shift + offset + ministep*np.array([int(name[-2])-1, int(name[-1])-1])
else:
print("Wrong filename. Image", i, "was not inserted")
continue
sup_path = os.path.join(dirname, '_'.join(name) + '_sup.' + parts[-1])
if not os.path.isfile(sup_path):
sup_path = None
df = addpic(path, sup_path, p0, ministep, annotation, threshold)
if df is None:
print("Cannot find 4 crosses in", i)
continue
full_df = full_df.append(df)
full_df.to_csv(os.path.join(dirname, "info.csv"), header=None, index=False)
return full_df
In [ ]:
image_formats = set(["png", "jpg", "tif", "tiff"])
def get_coords(cnt):
x, y = cnt.T[0][0], cnt.T[1][0]
histx, binsx = np.histogram(x, bins=min(200, max(x)-min(x)));
indsx = peakutils.indexes(histx, min_dist=3, thres=0.3)
if len(indsx) > 2:
new = sorted(indsx, key=lambda i: histx[i])
indsx = np.array(new[-2:])
histy, binsy = np.histogram(y, bins=min(200, max(y)-min(y)));
indsy = peakutils.indexes(histy, min_dist=3, thres=0.3)
if len(indsy) > 2:
new = sorted(indsy, key=lambda i: histy[i])
indsy = np.array(new[-2:])
if len(indsx) < 2 or len(indsy) < 2:
return None
return np.array([binsx[indsx[1]] + binsx[indsx[0]], binsy[indsy[1]] + binsy[indsy[0]]], dtype='int64') // 2
def addpic(path, sup_path, p0, step, annotation, threshold='Adaptive'):
'''
p0 - coords of left bottom cross on image (in um)
step - step in um from bottom left cross to the top right
supposed that crosses are vertexes of a rectangle
'''
# coordinates in microns - new points
i = np.array([1, 0])
j = np.array([0, 1])
new_pts = np.array([p0, p0 + step*i, p0 + step*j, p0 + step])
# coordinats in pixels - old points
old_pts = []
orig_img = cv.imread(path)
size_thres = min(orig_img.shape[:1]) * 0.06
img = orig_img
if sup_path is not None:
img = cv.imread(sup_path)
size_thres /= 2
if annotation is not None:
img = img[:int(img.shape[0] * (1-annotation))]
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
equ = cv.equalizeHist(gray)
if threshold == 'Adaptive':
thresh = cv.adaptiveThreshold(equ, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 61, 0)
else:
_, thresh = cv.threshold(equ, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)
kernel = np.ones((2, 2), np.uint8)
# Iteration over opening 'iterations' -- increasing contrast and
# checking if it is possible to distinguish 4 differenet crosses
itera = 1
while len(old_pts) != 4 and itera < 5:
old_pts = []
plot_contours = []
opening = cv.morphologyEx(thresh, cv.MORPH_OPEN, kernel, iterations=itera)
contours, hierarchy = cv.findContours(opening, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
for cnt in contours:
x, y, w, h = cv.boundingRect(cnt)
if w > size_thres and h > size_thres:
M = cv.moments(cnt)
centroid = np.array([int(M['m10'] / M['m00']), int(M['m01'] / M['m00'])])
bbox_center = np.array([x + w / 2, y + h / 2])
center = get_coords(cnt)
if center is not None:
# print(w / h < 1.33, w / h > 0.75,np.linalg.norm(centroid - center) < 0.2 * max(w,h),\
# np.linalg.norm(centroid - bbox_center) < 0.2 * max(w,h))
if w / h < 1.33 and w / h > 0.75 and np.linalg.norm(centroid - center) < 0.2 * max(w,h) and\
np.linalg.norm(centroid - bbox_center) < 0.2 * max(w,h) or sup_path is not None:
plot_contours.append(cnt)
old_pts.append([center[0] - orig_img.shape[1]/2, -center[1] + orig_img.shape[0]/2 + 1])
itera += 1
plot_img = orig_img
for cnt in plot_contours:
x, y, w, h = cv.boundingRect(cnt)
center = get_coords(cnt)
cv.rectangle(plot_img, (x, y), (x + w, y + h), (0, 255, 0), img.shape[0] // 400)
color = (rnd.randint(0, 256), rnd.randint(0, 256), rnd.randint(0, 256))
cv.drawContours(plot_img, [cnt], 0, color, img.shape[0] // 400, cv.LINE_8, hierarchy, 0)
cv.circle(plot_img, tuple(center), img.shape[0] // 200, (0, 0, 255), -1)
old_pts = np.array(sorted(old_pts, key=lambda p: 2*np.sign(p[1]) + np.sign(p[0])))
df = pd.DataFrame([[path] + list(old_pts.flatten()) + list(new_pts.flatten())])
fig, ax = plt.subplots(figsize=(7, 7 * orig_img.shape[0]/orig_img.shape[1]))
fig.tight_layout()
ax.imshow(plot_img, interpolation='none', cmap='gray');
if len(old_pts) != 4:
return None
return df
In [ ]:
dirname = "/home"
# Old designs with multifields
# df = add_images(dirname, offset=np.array([456, 576]), macrostep=np.array([1800, 1800]),\
# infield_shifts = np.array([[0, 0], [240, 0]]), step=np.array([16, 12]))
df = add_images_QDEV(dirname, threshold='Binary')
df = add_images_QDEV(dirname, annotation=0.0625, threshold='Adaptive')