利用Python分割图像的目标区域

本文介绍了一种基于图像处理和机器学习的方法,用于从复杂背景中精确分割和识别特定目标——鹰。首先通过灰度化、滤波和二值化等预处理步骤增强图像对比度,然后使用DBSCAN聚类算法定位目标轮廓,最后应用图像形态学操作细化边界并提取目标区域。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、目标

将下图中的鹰从图中分割出来
在这里插入图片描述

2、步骤

2.1 加载图片,进行灰度化

img_path = "bird.jpg"
img = cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow("img",gray)

2.2 对图片进行滤波,去掉不必要的像素点

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (9, 9),0) 
img2 = gray-blurred
cv2.imshow("img2",img2)

结果:
图片中相应的轮廓已经很清晰了,但是还需要去掉不相干的黑点。
在这里插入图片描述2.3、再次滤波

blurred = cv2.GaussianBlur(img2 , (9, 9),0)
(_, thresh) = cv2.threshold(blurred, 90, 255, cv2.THRESH_BINARY)
cv2.imshow("img3",thresh)

结果:
在这里插入图片描述2.4 图像的关键点边迹已成雏形了,现在需要进行聚类,这里我们选择DBSCAN算法,居于密度的聚类,算法实现:
主要步骤:
(1)取出黑色像素点的在图片中的坐标;
(2)利用DBSCAN算法对坐标值进行聚类;
(3)取出目标物体的聚类。

size_x = thresh.shape[0]
size_y = thresh.shape[1]
picture_data = np.array(thresh)
Pic_Data = []
#记录为黑色素像素点的为者
for i in range(size_x):
    for j in range(size_y):
        if picture_data[i][j] == 0:
            Pic_Data.append([i,j])
            #plt.plot(i,j,'o')
X=np.array(Pic_Data)
size=len(X)
y_pred = DBSCAN(eps = 40, min_samples = 10).fit_predict(X)
#plt.plot(X[0:size,1],X[0:size,0],'o')
Pic_Data_1 = []
for k in range(len(X)):
    if(y_pred[k]==0):
        Pic_Data_1.append(Pic_Data[k])
        
X=np.array(Pic_Data_1)
plt.plot(X[:, 0], X[:, 1],'o')
plt.show()

用plt.plot函数显示的结果:
在这里插入图片描述
2.5 根据聚类结果从原图中取出目标物体
二值图像如下图所示:
在这里插入图片描述

2.6 图像形态学

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (64, 64))
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
cv2.imshow("img5",closed)

在这里插入图片描述2.7 细节刻画

closed = cv2.erode(closed, None, iterations=16)
closed = cv2.dilate(closed, None, iterations=16)

在这里插入图片描述2.8 找出鹰的轮廓

def findcnts_and_box_point(closed):
    # 这里opencv3返回的是三个参数
    (_, cnts, _) = cv2.findContours(closed.copy(), 
        cv2.RETR_LIST, 
        cv2.CHAIN_APPROX_SIMPLE)
    c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]
    # compute the rotated bounding box of the largest contour
    rect = cv2.minAreaRect(c)
    box = np.int0(cv2.boxPoints(rect))
    
    return box

在这里插入图片描述

参考源码

在该博文(https://blog.youkuaiyun.com/sinat_36458870/article/details/78825571)提供的源码基础上进行了修改

import numpy as np
import cv2
from PIL import Image  
from scipy import ndimage
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN
def findcnts_and_box_point(closed):
    # 这里opencv3返回的是三个参数
    (_, cnts, _) = cv2.findContours(closed.copy(), 
        cv2.RETR_LIST, 
        cv2.CHAIN_APPROX_SIMPLE)
    c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]
    # compute the rotated bounding box of the largest contour
    rect = cv2.minAreaRect(c)
    box = np.int0(cv2.boxPoints(rect))
    
    return box

def drawcnts_and_cut(original_img, box):
    # 因为这个函数有极强的破坏性,所有需要在img.copy()上画
    # draw a bounding box arounded the detected barcode and display the image
    draw_img = cv2.drawContours(original_img.copy(), [box], -1, (0, 0, 255), 3)
    
    Xs = [i[0] for i in box]
    Ys = [i[1] for i in box]
    x1 = min(Xs)
    x2 = max(Xs)
    y1 = min(Ys)
    y2 = max(Ys)
    hight = y2 - y1
    width = x2 - x1
    crop_img = original_img[y1:y1+hight, x1:x1+width]
    
    return draw_img, crop_img


def image_morphology(thresh):
    # 建立一个椭圆核函数
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (48, 48))
    # 执行图像形态学, 细节直接查文档,很简单
    closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
    closed = cv2.erode(closed, None, iterations=4)
    closed = cv2.dilate(closed, None, iterations=4)
    
    return closed

def Thresh_and_blur(gradient):
    
    blurred = cv2.GaussianBlur(gradient, (9, 9),0)
    (_, thresh) = cv2.threshold(blurred, 90, 255, cv2.THRESH_BINARY)
    
    return thresh
    

img_path     = r'E:\my_project\bird.jpg'
original_img = cv2.imread(img_path)
gray=cv2.cvtColor(original_img,cv2.COLOR_BGR2GRAY)

blurred = cv2.GaussianBlur(gray, (9, 9),0) 
img2 = gray-blurred

blurred = cv2.GaussianBlur(img2, (9, 9),0)
(_, thresh) = cv2.threshold(blurred, 90, 255, cv2.THRESH_BINARY)


size_x = thresh.shape[0]
size_y = thresh.shape[1]
picture_data = np.array(thresh)
Pic_Data = []
#记录为黑色素像素点的为者
for i in range(size_x):
    for j in range(size_y):
        if picture_data[i][j] == 0:
            Pic_Data.append([i,j])
            #plt.plot(i,j,'o')
X=np.array(Pic_Data)
size=len(X)
y_pred = DBSCAN(eps = 40, min_samples = 10).fit_predict(X)
#plt.plot(X[0:size,1],X[0:size,0],'o')
Pic_Data_1 = []
for k in range(len(X)):
    if(y_pred[k]==0):
        Pic_Data_1.append(Pic_Data[k])
        
X=np.array(Pic_Data_1)
plt.plot(X[:, 0], X[:, 1],'o')
plt.show()

Test_Pic = [[255 for i in range(size_y)] for j in range(size_x)]
Test_Pic = np.array(Test_Pic)
#X=np.array(Pic_Data_1,dtype=np.uint8)

for X_Index in X:
    Test_Pic[X_Index[0]][X_Index[1]]=0


thresh=np.array(Test_Pic,dtype=np.uint8)

gray = thresh
gradX = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=1, dy=0) 
gradY = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=0, dy=1) 
gradient = cv2.subtract(gradX, gradY) 

thresh = gradient
thresh = Thresh_and_blur(gradient)

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (40, 40))
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
closed = cv2.erode(closed, None, iterations=16)
closed = cv2.dilate(closed, None, iterations=16)

#closed = image_morphology(thresh)
closed = np.array(closed,np.uint8)
box = findcnts_and_box_point(closed)
draw_img, crop_img = drawcnts_and_cut(original_img,box)

cv2.imshow('original_img', original_img)
cv2.imshow('blurred', blurred)
cv2.imshow('gradX', gradX)
cv2.imshow('gradY', gradY)
cv2.imshow('final', gradient)
cv2.imshow('thresh', thresh)
cv2.imshow('closed', closed)
cv2.imshow('draw_img', draw_img)
cv2.imshow('crop_img', crop_img)
cv2.waitKey(200)
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值