Opencv-Python提取掌纹图片ROI

参考文章:基于图像相位及方向特征的掌纹识别的c++实现(二) - 知乎 (zhihu.com)

代码已经通过测试,可以跑通。

  

完整源码如下:

import math
import cv2
import numpy as np

PI = 3.14159265
debug = 1

img_path = './PolyU_00_1.bmp'
src = cv2.imread(img_path,0)
if src is None:
    print('图片没读到')
    exit(0)
if debug:
    cv2.imshow("src",src)

#2.1 crop image
crop_img = src[0:284, 40:200]
if debug:
    cv2.imshow("crop_img",crop_img)

#2.2 low-pass Gaussion Filter
before_Gaussion = np.zeros((284,160),dtype = np.int)
roi = crop_img[7:crop_img.shape[0]-7,7:crop_img.shape[1]-7]
before_Gaussion[7:crop_img.shape[0]-7,7:crop_img.shape[1]-7] = roi.copy()
Gaussion_img = cv2.GaussianBlur(np.uint8(before_Gaussion),(15,15),2,2)
if debug:
    cv2.imshow("Gaussion_img",Gaussion_img)

#2.3 thresholding
ret,Binary_img = cv2.threshold(Gaussion_img,20,1,0)
if debug:
    Binary_img_for_show = cv2.normalize(Binary_img, None, 0, 255, 32)
    cv2.imshow("Binary_img",Binary_img_for_show)

#2.4 Find Reference Points
#(a)Find External Reference Point
Out_top =  (0,0)
Out_bottom = (0,0)
for row in range(Binary_img.shape[0]):
    is_get = 0
    for col in range(Binary_img.shape[1]):
        if Binary_img[row][col] == 1:
            Out_top = (col,row)
            is_get = 1
            break
    if is_get:
        break
for row in range(Binary_img.shape[0]-1, -1, -1):
    is_get = 0
    for col in range(Binary_img.shape[1]):
        if Binary_img[row][col] == 1:
            Out_bottom = (col, row)
            is_get = 1
            break
    if is_get:
        break
if debug:
    print("Out_top(x,y):{}".format(Out_top))
    print("Out_bottom(x,y):{}".format(Out_bottom))

#(b)Find Internal Reference Point
In_top = (0,0)
In_bottom =(0,0)
gap_x = 0
for col in range(Binary_img.shape[1]):
    gap_width = 0
    for row in range(Binary_img.shape[0]):
        if Binary_img[row][col] == 0:
            gap_width += 1
    if gap_width < 200:
        gap_x = col
        break
In_top = (gap_x, 0)
In_bottom = (gap_x, 0)
center_y = Binary_img.shape[0] // 2
for row in range(center_y,-1,-1):
    if Binary_img[row][gap_x] == 1:
        In_top = (gap_x, row)
        break
for row in range(center_y,Binary_img.shape[0]):
    if Binary_img[row][gap_x] == 1:
        In_bottom = (gap_x,row)
        break
if debug:
    print('In_top(x,y):{}'.format(In_top))
    print('In_bottom(x,y):{}'.format(In_bottom))

#2.5.1 Find Countours
Out_top_j = Out_bottom_j = In_top_j = In_bottom_j = 0
reference_point_num = 0
contours, hierarchy = cv2.findContours(Binary_img,0,1)
Contours = np.zeros(Binary_img.shape,np.int)
for j in range(len(contours[0])):
    if contours[0][j][0][0] == Out_top[0] and contours[0][j][0][1] == Out_top[1]:
        Out_top_j = j
        reference_point_num += 1
    if contours[0][j][0][0] == Out_bottom[0] and contours[0][j][0][1] == Out_bottom[1]:
        Out_bottom_j = j
        reference_point_num += 1
    if contours[0][j][0][0] == In_top[0] and contours[0][j][0][1] == In_top[1]:
        In_top_j = j
        reference_point_num += 1
    if contours[0][j][0][0] == In_bottom[0] and contours[0][j][0][1] == In_bottom[1]:
        In_bottom_j = j
        reference_point_num += 1
if reference_point_num != 4:
    print('not four')
    exit(0)
for j in range(Out_top_j,In_top_j+1):
    P = (contours[0][j][0][0], contours[0][j][0][1])
    Contours[P[1]][P[0]] = 255
for j in range(In_bottom_j,Out_bottom_j+1):
    P = (contours[0][j][0][0], contours[0][j][0][1])
    Contours[P[1]][P[0]] = 255

#2.5.2 Key Point Positioning
Top_x = Bottom_x = 0.0
Top_y_vector = []
Bottom_y_vector = []
for j in range(Out_top_j,In_top_j+1):
    if contours[0][j][0][0] > Top_x:
        Top_x = contours[0][j][0][0]
for j in range(In_bottom_j,Out_bottom_j+1):
    if contours[0][j][0][0] > Bottom_x:
        Bottom_x = contours[0][j][0][0]
for j in range(Out_top_j,In_top_j+1):
    if contours[0][j][0][0] == Top_x:
        Top_y_vector.append(contours[0][j][0][1])
for j in range(In_bottom_j,Out_bottom_j+1):
    if contours[0][j][0][0] == Bottom_x:
        Bottom_y_vector.append(contours[0][j][0][1])

top_sum = sum(Top_y_vector)
bottom_sum = sum(Bottom_y_vector)
Top_y = top_sum / float(len(Top_y_vector))
Bottom_y = bottom_sum / float(len(Bottom_y_vector))

print('Top:({},{})'.format(Top_x,Top_y))
print('Bottom:({},{})'.format(Bottom_x,Bottom_y))

#2.6 Build a Coordinate System on the Oridinal Image
Top = (Top_x + 40, Top_y)
Bottom = (Bottom_x + 40, Bottom_y)
Origin_X = (Top[0] + Bottom[0]) / 2.0
Origin_Y = (Top[1] + Bottom[1]) / 2.0
Origin = (Origin_X, Origin_Y)
Slope_y_axis = (Top_y - Bottom_y) / (Top_x - Bottom_x)
Slope_x_axis = -1 / Slope_y_axis

angle = -1 * math.atan(1 / Slope_y_axis) * (180 / PI)
rotated_sz = (src.shape[1], src.shape[0])
center = (Origin_X, Origin_Y)
rot_mat = cv2.getRotationMatrix2D(center, angle, 1.0)
Rotated_img = cv2.warpAffine(src, rot_mat, rotated_sz, 1, 0)
dst = Rotated_img.copy()
Uleft = (int(Origin_X + 50), int(Origin_Y - 128 / 2))
dst = dst[Uleft[1]:Uleft[1]+128, Uleft[0]:Uleft[0]+128]
if debug:
    cv2.imshow("dst",dst)

if debug:
    cv2.waitKey(0)
### 基于最大内切圆法的掌纹ROI提取计算机视觉领域,利用OpenCV可以高效地实现图像处理中的特定目标检测任务。对于掌纹ROI(感兴趣区域)提取问题,可以通过计算手掌轮廓的最大内切圆来定位并裁剪出感兴趣的区域。 以下是基于PythonOpenCV实现该方法的具体过程: #### 1. 图像预处理 为了更好地识别手掌轮廓,通常需要对原始图像进行二值化处理以及形态学操作以去除噪声[^1]。 ```python import cv2 import numpy as np def preprocess_image(image): gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 转换为灰度图 blurred = cv2.GaussianBlur(gray, (5, 5), 0) # 高斯模糊去噪 _, binary = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # 自适应阈值分割 kernel = np.ones((3, 3), dtype=np.uint8) morphed = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel) # 形态闭运算填充孔洞 return morphed ``` #### 2. 手掌轮廓提取 通过查找连通域的方式找到最大的手掌轮廓,并将其作为后续计算的基础。 ```python def find_palm_contour(binary_image): contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) palm_contour = max(contours, key=cv2.contourArea) # 获取面积最大的轮廓 return palm_contour ``` #### 3. 计算最大内切圆 使用`cv2.minEnclosingCircle()`函数可以直接获得包围给定轮廓的最小外接圆中心及其半径;而最大内切圆则需进一步优化求解,在此我们假设其近似等于最小外接圆的一部分。 ```python def compute_max_inscribed_circle(palm_contour): (center_x, center_y), radius = cv2.minEnclosingCircle(palm_contour) center = (int(center_x), int(center_y)) radius = int(radius * 0.9) # 缩小一定比例模拟最大内切圆效果 return center, radius ``` #### 4. 提取ROI区域 最后依据得到的圆形参数截取出对应的矩形范围内的子图像即为目标掌纹ROI部分。 ```python def extract_roi(original_image, center, radius): x, y = center roi = original_image[y-radius:y+radius, x-radius:x+radius] return roi ``` 完整的代码流程如下所示: ```python if __name__ == "__main__": image_path = 'palm.jpg' img = cv2.imread(image_path) processed_img = preprocess_image(img) contour = find_palm_contour(processed_img) circle_center, circle_radius = compute_max_inscribed_circle(contour) roi_region = extract_roi(img, circle_center, circle_radius) cv2.imshow('Palm ROI', roi_region) cv2.waitKey(0) cv2.destroyAllWindows() ``` 上述方法能够较为精确地完成掌纹ROI的自动提取工作,适用于多种实际应用场景之中。
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值