文档服务地址:http://47.92.0.57:3000/ 周报索引地址:http://47.92.0.57:3000/s/NruNXRYmV

Commit 069bac67 by 王肇一

Image process toolkit v0.2

parents
img/*
out/*
__pycache__/
.idea
\ No newline at end of file
# 使用说明
## 安装依赖
`pip install -r requirement.txt`
## 目录结构
```.
├── README.md
├── img
│ └── folders
│ └── imgs
├── out
│ ├── csv
│ │ └── result
│ └── graph
│ └── processed images
├── main.py
└── util.py
```
## 参数
* -m ,--method : 0 使用Kmeans,1 使用阈值法(butterworth滤波),2 使用阈值法(fft)。默认Kmeans
* -c ,--core : Kmeans分为几类,默认5,仅对Kmeans法有效
* -p ,--process : 使用线程数量,默认8,仅对阈值法有效
## 示例
- `python main.py -m 1 -p 16`
- `python main.py -m 0 -c 8`
## 版本
|版本号|功能|
|:---:|:---|
|v0.1|实现了Kmeans、阈值法两种分割方法,提供命令行工具|
|v0.2|1.更新了滤波算法<br>2.修改了一些小bug<br>3.对部分函数进行解耦|
\ No newline at end of file
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import numpy as np
def butterworth(img, d, n):
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
mask = np.zeros(img.shape)
center = tuple(map(lambda x: (x - 1) / 2, img.shape))
for i in range(mask.shape[0]):
for j in range(mask.shape[1]):
def cal_distance(pa, pb):
from math import sqrt
return sqrt((pa[0] - pb[0]) ** 2 + (pa[1] - pb[1]) ** 2)
dis = cal_distance(center, (i, j))
mask[i, j] = 1 - 1 / ((1 + (d / dis)) ** n)
if dis < 1:
mask[i, j] = 1
# mask[100,:] = 0
new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift * mask)))
return new_img.astype(np.uint8)
def fft_mask(img, d):
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
mask = np.zeros(img.shape)
center = tuple(map(lambda x: (x - 1) / 2, img.shape))
for i in range(mask.shape[0]):
for j in range(mask.shape[1]):
def cal_distance(pa, pb):
from math import sqrt
return sqrt((pa[0] - pb[0]) ** 2 + (pa[1] - pb[1]) ** 2)
dis = cal_distance(center, (i, j))
mask[i, j] = 0 if dis > d else 1
new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift * mask))).astype(np.uint8)
return new_img
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from sklearn.cluster import KMeans
from util import *
from filters import butterworth,fft_mask
def kmeans(pair, cluster_num = 5,filter='butter'):
img_list = pre(pair,'clahe',filter)
denoise = img_list['denoise']
km = KMeans(n_clusters = cluster_num)
feature = [[denoise[k, j]] for k in range(200) for j in range(200)]
ll = km.fit_predict(feature)
mask = [np.array([x for x in map(lambda x: 255 if x == i else 0, ll)]).reshape([200, 200]) for i in
range(cluster_num)]
edge = select_mask(img_list['ori'], mask).astype(np.uint8)
return edge
def kmeans_back(pair, edge):
img_list = pre(pair, 'clahe', filter)
kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (3, 3))
close = cv.morphologyEx(edge, cv.MORPH_CLOSE, kernel, iterations = 5)
img_list['close'] = close
save_img(img_list, pair[0], pair[1][:-4])
calcRes(img_list['ori'], img_list['close'], pair[0], pair[1][:-4])
def select_mask(ori_img, mask_list):
num = len(mask_list) + 1
plt.figure(figsize = (100, 20))
plt.title('ori_img')
plt.subplot(1, num, 1)
plt.imshow(ori_img, 'gray')
for i, mask in enumerate(mask_list):
plt.subplot(1, num, i + 2)
plt.title('mask ' + str(i))
plt.imshow(mask, 'gray')
plt.show()
i = input('Which mask fits the signal best (int): ')
plt.close()
return mask_list[int(i)]
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from multiprocessing import Pool
from tqdm import tqdm
import argparse
from util import *
from kmeans import kmeans, kmeans_back
from threshold import threshold
def method_kmeans(imglist, core = 5):
edges = [kmeans(x, core) for x in imglist]
for pair, edge in tqdm(zip(path, edges)):
kmeans_back(pair, edge)
def method_threshold(imglist, process = 8):
pool = Pool(process)
pool.map(threshold, imglist)
pool.close()
pool.join()
def method_newThreshold(imglist, process = 8):
pool = Pool(process)
pool.map(lambda x: threshold(x,'fft'), imglist)
pool.close()
pool.join()
def get_args():
parser = argparse.ArgumentParser(description = 'Identify targets from background by KMeans or Threshold',
formatter_class = argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-m', '--method', metavar = 'M', type = int, default = 0,
help = '0 for KMeans; 1 for Threshold; 2 for newThreshold', dest = 'method')
#parser.add_argument('-o', '--out', metavar = 'O', type = str, default = './out', help = 'Path to output',
# dest = 'out')
parser.add_argument('-c', '--core', metavar = 'C', type = int, default = 5, help = 'Num of cluster', dest = 'core')
parser.add_argument('-p', '--process', metavar = 'P', type = int, default = 8, help = 'Num of process',
dest = 'process')
return parser.parse_args()
if __name__ == '__main__':
args = get_args()
path = [(y, x) for y in os.listdir(args.dir) for x in filter(
lambda x: x.endswith('.tif') and not x.endswith('dc.tif') and not x.endswith('DC.tif') and not x.endswith(
'dc .tif'), os.listdir('img/' + y))]
if args.method == 0:
method_kmeans(path,args.core)
elif args.method == 1:
method_threshold(path,args.process)
elif args.method == 2:
method_newThreshold(path,args.process)
scikit-learn
pandas
tqdm
matplotlib
numpy
opencv-python
\ No newline at end of file
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from util import *
from filters import butterworth, fft_mask
def threshold(pair,filter='butter'):
img_list =pre(pair,filter)
edge = cv.Canny(img_list['blr'], 40, 100)
kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (3, 3))
close = cv.morphologyEx(edge, cv.MORPH_CLOSE, kernel, iterations = 5)
open = cv.morphologyEx(close, cv.MORPH_OPEN, kernel, iterations = 3)
img_list['edge']=edge
img_list['close'] = close
img_list['open'] = open
save_img(img_list,pair[0],pair[1][:-4])
calcRes(img_list['ori'], img_list['open'], pair[0], pair[1][:-4])
\ No newline at end of file
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import numpy as np
import cv2 as cv
import pandas as pd
import matplotlib.pyplot as plt
import logging
import os
from filters import fft_mask,butterworth
def remove_scratch(img):
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
fshift[100, 0:90] = 0
fshift[100, 110:] = 0
transed = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift))).astype(np.uint8)
return transed
def unevenLightCompensate(img, blockSize, GaussianBlur_kernelsize = 7):
gray = img
average = np.mean(gray)
rows_new = int(np.ceil(gray.shape[0] / blockSize))
cols_new = int(np.ceil(gray.shape[1] / blockSize))
blockImage = np.zeros((rows_new, cols_new), dtype = np.float32)
for r in range(rows_new):
for c in range(cols_new):
rowmin = r * blockSize
rowmax = (r + 1) * blockSize
if (rowmax > gray.shape[0]):
rowmax = gray.shape[0]
colmin = c * blockSize
colmax = (c + 1) * blockSize
if (colmax > gray.shape[1]):
colmax = gray.shape[1]
imageROI = gray[rowmin:rowmax, colmin:colmax]
temaver = np.mean(imageROI)
blockImage[r, c] = temaver
blockImage = blockImage - average
blockImage2 = cv.resize(blockImage, (gray.shape[1], gray.shape[0]), interpolation = cv.INTER_CUBIC)
gray2 = gray.astype(np.float32)
dst = gray2 - blockImage2
dst = dst.astype(np.uint8)
# dst = cv.GaussianBlur(dst, (GaussianBlur_kernelsize, GaussianBlur_kernelsize), 0)
return dst
def pre(pair,even='clahe',filter='butter'):
lab = pair[0]
pic = pair[1]
img = cv.imread('img/' + lab + '/' + pic, 0)
even = unevenLightCompensate(img, 40) if even== 'light' else cv.createCLAHE(clipLimit = 2.0, tileGridSize = (8, 8)).apply(img)
filtered = fft_mask(even, 10) if filter == 'fft' else butterworth(even, 10, 2)
denoise = cv.fastNlMeansDenoising(even)
blr = cv.GaussianBlur(denoise, (7, 7), 0)
return {'ori': img, 'even': even, 'filtered': filtered, 'denoise': denoise, 'blr': blr}
def save_img(img_list, dir, name):
num = len(img_list)
plt.figure(figsize = (100, 20))
plt.suptitle(name)
for i, title in zip(range(num), img_list):
img = img_list[title]
plt.subplot(1, num, i + 1)
plt.title(title)
plt.imshow(img, 'gray')
try:
os.makedirs('out/' + dir + '/graph')
except:
logging.info('Existing dir: out/' + dir + '/graph')
plt.savefig('out/' + dir + '/graph/' + name + '.png')
plt.close()
def calcRes(img, mask, dir = 'output', name = 'output'):
dic = get_subarea_infor(img, mask)
df = pd.DataFrame(dic)
try:
os.makedirs('out/' + dir + '/csv')
except:
logging.info('Existing dir: out/' + dir + '/csv')
df.to_csv('out/' + dir + '/csv/' + name + '.csv')
def get_subarea_infor(img, mask):
area_num, labels, stats, centroids = cv.connectedComponentsWithStats(mask)
label_group = []
area_group = []
mean_group = []
std_group = []
back_mean = []
back_std = []
for i in filter(lambda x: x != 0, range(area_num)):
group = np.where(labels == i)
img_value = img[group]
area_tmp = len(group[0])
mean_tmp = np.mean(img_value)
std_tmp = np.std(img_value)
pos = [(group[0][i], group[1][i]) for i in range(len(group[0]))]
res = np.zeros([200, 200], np.uint8)
for x in range(200):
for y in range(200):
if (x, y) in pos:
res[x, y] = mask[x, y]
else:
res[x, y] = 0
kernel = np.ones((17, 17), np.uint8)
mask_background = cv.erode(255 - res, kernel)
minimask = cv.bitwise_xor(mask_background, 255 - res)
img_background = img[np.where(minimask != 0)]
mean_value = np.mean(img_background)
std_value = np.std(img_background)
label_group.append(i)
area_group.append(area_tmp)
mean_group.append(mean_tmp)
std_group.append(std_tmp)
back_mean.append(mean_value)
back_std.append(std_value)
return {'Label': label_group, 'Area': area_group, 'Mean': mean_group, 'Std': std_group, 'BackMean': back_mean,
'BackStd': back_std}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment