基于图像处理的皱纹检测算法。
https://github.com/bulingda/Wrinkles_detection/blob/master/Wrinkle.py
基于RCNN 毛孔检测
https://github.com/jack16888/Faster-RCNN-for-pore-detection
from PIL import Image | |
import cv2 | |
import time | |
import numpy as np | |
from skimage.filters import frangi, gabor | |
from skimage import measure, morphology | |
from Partition import practice14 as pa | |
# | |
# class UnionFindSet(object): | |
# | |
# def __init__(self, m): | |
# # m, n = len(grid), len(grid[0]) | |
# self.roots = [i for i in range(m)] | |
# self.rank = [0 for i in range(m)] | |
# self.count = m | |
# | |
# for i in range(m): | |
# self.roots[i] = i | |
# | |
# def find(self, member): | |
# tmp = [] | |
# while member != self.roots[member]: | |
# tmp.append(member) | |
# member = self.roots[member] | |
# for root in tmp: | |
# self.roots[root] = member | |
# return member | |
# | |
# def union(self, p, q): | |
# parentP = self.find(p) | |
# parentQ = self.find(q) | |
# if parentP != parentQ: | |
# if self.rank[parentP] > self.rank[parentQ]: | |
# self.roots[parentQ] = parentP | |
# elif self.rank[parentP] < self.rank[parentQ]: | |
# self.roots[parentP] = parentQ | |
# else: | |
# self.roots[parentQ] = parentP | |
# self.rank[parentP] -= 1 | |
# self.count -= 1 | |
# | |
# | |
# class Solution(object): | |
# def countComponents(self, n, edges): | |
# """ | |
# :type n: int | |
# :type edges: List[List[int]] | |
# :rtype: int | |
# """ | |
# ufs = UnionFindSet(n) | |
# # print ufs.roots | |
# for edge in edges: | |
# start, end = edge[0], edge[1] | |
# ufs.union(start, end) | |
# | |
# return ufs.count | |
# | |
# | |
# # def connected_component(thresh_A): | |
# # thresh_A_copy = thresh_A.copy() # 复制thresh_A到thresh_A_copy | |
# # thresh_B = np.zeros(thresh_A.shape).astype(int) # thresh_B大小与A相同,像素值为0 | |
# # | |
# # kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3)) # 3×3结构元 | |
# # | |
# # count = [] # 为了记录连通分量中的像素个数 | |
# # xy_count = [] | |
# # # 循环,直到thresh_A_copy中的像素值全部为0 | |
# # while thresh_A_copy.any(): | |
# # Xa_copy, Ya_copy = np.where(thresh_A_copy > 0) # thresh_A_copy中值为255的像素的坐标 | |
# # thresh_B[Xa_copy[0]][Ya_copy[0]] = 1 # 选取第一个点,并将thresh_B中对应像素值改为255 | |
# # | |
# # # 连通分量算法,先对thresh_B进行膨胀,再和thresh_A执行and操作(取交集) | |
# # for i in range(thresh_A.shape[0]): | |
# # dilation_B = cv2.dilate(thresh_B, kernel, iterations=1) | |
# # print(type(thresh_A), type(dilation_B.astype(int))) | |
# # thresh_B = cv2.bitwise_and(np.uint8(thresh_A), dilation_B.astype(int)) | |
# # | |
# # # 取thresh_B值为255的像素坐标,并将thresh_A_copy中对应坐标像素值变为0 | |
# # Xb, Yb = np.where(thresh_B > 0) | |
# # thresh_A_copy[Xb, Yb] = 0 | |
# # xy_count.append(np.c_[Xb, Yb]) | |
# # # 显示连通分量及其包含像素数量 | |
# # count.append(len(Xb)) | |
# # if len(count) == 0: | |
# # print("无连通分量") | |
# # if len(count) == 1: | |
# # print("第1个连通分量为{}".format(count[0])) | |
# # print(xy_count[0], "2") | |
# # ecc = measure.regionprops(xy_count[0]) | |
# # print(ecc[0].eccentricity) | |
# # if len(count) >= 2: | |
# # if (count[-1] - count[-2]) < 2: | |
# # continue | |
# # print("第{}个连通分量为{}".format(len(count), count[-1] - count[-2])) | |
# # print(xy_count[len(count) - 1][len(xy_count[-2]):len(xy_count[-1])], "2") | |
# # ecc = measure.regionprops(xy_count[len(count) - 1][len(xy_count[-2]):len(xy_count[-1])]) | |
# # print(ecc[0].eccentricity) | |
# def connected_component(path): | |
# img_A = cv2.imread(path) | |
# gray_A = cv2.cvtColor(img_A, cv2.COLOR_BGR2GRAY) # 转换成灰度图 | |
# ret, thresh_A = cv2.threshold(gray_A, 20, 255, cv2.THRESH_BINARY_INV) # 灰度图转换成二值图像 | |
# print(thresh_A, "thresh_A") | |
# thresh_A_copy = thresh_A.copy() # 复制thresh_A到thresh_A_copy | |
# thresh_B = np.zeros(thresh_A.shape, np.uint8) # thresh_B大小与A相同,像素值为0 | |
# | |
# kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)) # 3×3结构元 | |
# | |
# count = [] # 为了记录连通分量中的像素个数 | |
# xy_count = [] | |
# # 循环,直到thresh_A_copy中的像素值全部为0 | |
# while thresh_A_copy.any(): | |
# Xa_copy, Ya_copy = np.where(thresh_A_copy > 0) # thresh_A_copy中值为255的像素的坐标 | |
# thresh_B[Xa_copy[0]][Ya_copy[0]] = 255 # 选取第一个点,并将thresh_B中对应像素值改为255 | |
# | |
# # 连通分量算法,先对thresh_B进行膨胀,再和thresh_A执行and操作(取交集) | |
# for i in range(200): | |
# dilation_B = cv2.dilate(thresh_B, kernel, iterations=1) | |
# thresh_B = cv2.bitwise_and(thresh_A, dilation_B) | |
# | |
# # 取thresh_B值为255的像素坐标,并将thresh_A_copy中对应坐标像素值变为0 | |
# Xb, Yb = np.where(thresh_B > 0) | |
# thresh_A_copy[Xb, Yb] = 0 | |
# xy_count.append(np.c_[Xb, Yb]) | |
# # 显示连通分量及其包含像素数量 | |
# count.append(len(Xb)) | |
# if len(count) == 0: | |
# print("无连通分量") | |
# if len(count) == 1: | |
# print("第1个连通分量为{}".format(count[0])) | |
# # print(np.c_[Xb, Yb], "1") | |
# print(xy_count[0], "2") | |
# | |
# ecc = measure.regionprops(xy_count[0]) | |
# print(ecc[0].eccentricity) | |
# if len(count) >= 2: | |
# if (count[-1] - count[-2]) < 2: | |
# continue | |
# print("第{}个连通分量为{}".format(len(count), count[-1] - count[-2])) | |
# # print(np.c_[Xb, Yb], "1") | |
# print(xy_count[len(count) - 1][len(xy_count[-2]):len(xy_count[-1])], "2") | |
# ecc = measure.regionprops(xy_count[len(count) - 1][len(xy_count[-2]):len(xy_count[-1])]) | |
# print(ecc[0].eccentricity) | |
def master_control(image): | |
# image = cv2.resize(image, (int(image.shape[1]*0.3), int(image.shape[0]*0.3)), interpolation=cv2.INTER_CUBIC) # 图片分辨率很大是要变小 | |
b, g, r = cv2.split(image) # image | |
sk_frangi_img = frangi(g, scale_range=(0, 1), scale_step=0.01, beta1=1.5, beta2=0.01) # 线宽范围,步长,连接程度(越大连接越多),减少程度(越大减得越多)0.015 | |
sk_frangi_img = morphology.closing(sk_frangi_img, morphology.disk(1)) | |
sk_gabor_img_1, sk_gabor_1 = gabor(g, frequency=0.35, theta=0) | |
sk_gabor_img_2, sk_gabor_2 = gabor(g, frequency=0.35, theta=45) # 越小越明显 | |
sk_gabor_img_3, sk_gabor_3 = gabor(g, frequency=0.35, theta=90) | |
sk_gabor_img_4, sk_gabor_4 = gabor(g, frequency=0.35, theta=360) # 横向皱纹 | |
sk_gabor_img_1 = morphology.opening(sk_gabor_img_1, morphology.disk(2)) | |
sk_gabor_img_2 = morphology.opening(sk_gabor_img_2, morphology.disk(1)) | |
sk_gabor_img_3 = morphology.opening(sk_gabor_img_3, morphology.disk(2)) | |
sk_gabor_img_4 = morphology.opening(sk_gabor_img_4, morphology.disk(2)) | |
all_img = cv2.add(0.1 * sk_gabor_img_2, 0.9 * sk_frangi_img) # + 0.02 * sk_gabor_img_1 + 0.02 * sk_gabor_img_2 + 0.02 * sk_gabor_img_3 | |
all_img = morphology.closing(all_img, morphology.disk(1)) | |
_, all_img = cv2.threshold(all_img, 0.3, 1, 0) | |
img1 = all_img | |
# print(all_img, all_img.shape, type(all_img)) | |
# contours, image_cont = cv2.findContours(all_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) | |
# all_img = all_img + image_cont | |
bool_img = all_img.astype(bool) | |
label_image = measure.label(bool_img) | |
count = 0 | |
for region in measure.regionprops(label_image): | |
if region.area < 10: # or region.area > 700 | |
x = region.coords | |
for i in range(len(x)): | |
all_img[x[i][0]][x[i][1]] = 0 | |
continue | |
if region.eccentricity > 0.98: | |
count += 1 | |
else: | |
x = region.coords | |
for i in range(len(x)): | |
all_img[x[i][0]][x[i][1]] = 0 | |
skel, distance = morphology.medial_axis(all_img.astype(int), return_distance=True) | |
skels = morphology.closing(skel, morphology.disk(1)) | |
trans1 = skels # 细化 | |
return skels, count # np.uint16(skels.astype(int)) | |
def face_wrinkle(path): | |
# result = pa.curve(path, backage) | |
result = cv2.imread(path) | |
img, count = master_control(result) | |
print(img.astype(float)) | |
result[img > 0.1] = 255 | |
cv2.imshow("result", img.astype(float)) | |
cv2.waitKey(0) | |
if __name__ == '__main__': | |
path = r"D:\E\document\datas\line\2885.png" | |
backage = r'..\Sebum\shape_predictor_81_face_landmarks.dat' | |
face_wrinkle(path) |