python实现批量处理图片:K-means聚类分割、开运算、画目标区域框,切割目标区域

 做SAR图像分类预处理时用到K-means聚类把前景后景分开。由于聚类效果不太理想,总有些错分的像素点和目标区域不闭合的情况,且目标区域的边缘也不够平滑,所以在K-means之后还进行了一些后续操作,包括二值化处理,开运算等操作,再进行目标区域定位画框,效果就好很多。

完整代码和注释如下:

# -*- coding: utf-8 -*-
# autho:xier
​​​​​​​
import cv2
import os
import math
import numpy as np
import PIL.Image as image
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from pylab import mpl
mpl.rcParams['font.sans-serif'] = 'NSimSun, Times New Roman'

# 加载图片,转成矩阵
def load_data(file_path):
    f = open(file_path, 'rb')  # 二进制打开
    data = []
    img = image.open(f)  # 以列表形式返回图片像素值
    m, n = img.size  # 图片大小
    for i in range(m):
        for j in range(n):  # 将每个像素点RGB颜色处理到0-1范围内并存放data
            x = img.getpixel((i, j))
            data.append([x/256.0])
    f.close()
    return np.mat(data), m, n  # 以矩阵型式返回data,图片大小

def K_means(img_data, row, col):
    label = KMeans(n_clusters=2, n_init=40, init='k-means++').fit_predict(img_data)  # 聚成两类
    label = label.reshape([row, col])  # 聚类获得每个像素所属的类别
    if np.sum(label) >= row * col/2:  #分类相反
        label = np.abs(np.ones((row, col)) - label)
    pic_k = image.new("L", (row, col))  # 创建一张新的灰度图保存聚类后的结果
    for i in range(row):  # 根据所属类别向图片中添加灰度值
        for j in range(col):
            pic_k.putpixel((i, j), int(256 / (label[i][j] + 1)))
    return pic_k

# 对K_means聚类分割后的图像进行阈值分割转成二值图像
def Thresh_and_blur(img):

    (_, thresh) = cv2.threshold(img, 130, 255, cv2.THRESH_BINARY)

    return thresh

# 用数字形态学先腐蚀掉噪声再进行膨胀(开运算)
def image_morphology(thresh):
    # 建立一个椭圆核函数
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (10, 10))
    # 执行图像形态学
    opened = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
    # closed = cv2.morphologyEx(opened, cv2.MORPH_CLOSE, kernel)
    #opened = cv2.erode(opened, None, iterations=4)  # 腐蚀4次
    #opened = cv2.dilate(opened, None, iterations=4)  # 膨胀4次
    return opened

def findcnts_and_box_point(opened):
    # 这里opencv3返回的是三个参数,源图像、轮廓信息、可选参数
    # 轮廓检索模式:cv2.RETR_LIST表示提取所有轮廓并记录在列表
    # 轮廓逼近方法:cv2.CHAIN_APPROX_SIMPLE,压缩水平、垂直、对角元素,保留终点坐标,如矩形轮廓用4个角点表示
    (_, cnts, _) = cv2.findContours(opened.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    c = sorted(cnts, key=cv2.contourArea, reverse=True)
    c = c[1]
    # compute the rotated bounding box of the largest contour
    rect = cv2.minAreaRect(c)  # 生成最小外接矩形,retval包含中心坐标、矩形宽高和旋转角度
    box = np.int0(cv2.boxPoints(rect))  # 得到旋转矩阵四个顶点坐标

    return box

def drawcnts_and_cut(original_img, box):
    # 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)
    y_mid = y1 + math.ceil((y2 - y1)/2)
    x_mid = x1 + math.ceil((x2 - x1) / 2)

    crop_img = original_img[y_mid-25:y_mid+25, x_mid-25:x_mid+25]  # 裁成50*50目标图像

    return draw_img, crop_img

def walk():

    original_Folder = '自己存放图片的文件夹'
    OR_Vector = os.listdir(original_Folder)  # 读取待处理文件夹中所有的文件
    for k in range(len(OR_Vector)):
        # 取一个类别文件夹
        Class_Folder = os.path.join('%s\%s' % (original_Folder, OR_Vector[k]))
        # 读取该类别文件夹的所有图片
        CF_Tensor = os.listdir(Class_Folder)
        for p in range(len(CF_Tensor)):  # 取一张图片
            # 取一张图片
            Image_Path = os.path.join('%s\%s' % (Class_Folder, CF_Tensor[p]))
            original_img = cv2.imread(Image_Path)
            img_data, row, col = load_data(Image_Path)
            pic_k = K_means(img_data, row, col)
            pic_k = np.asarray(pic_k)
            thresh = Thresh_and_blur(pic_k)
            opened = image_morphology(thresh)
            box = findcnts_and_box_point(opened)
            draw_img, crop_img = drawcnts_and_cut(original_img, box)

            # 保存切割后的图片
            # Save_Folder = 'F:\pycharm\\test_IO\\MSTAR-10_denoise_enl4\\train_denoise_enl4_segment'
            # SA_Vector = os.listdir(Save_Folder)  # 读取保存的文件夹中所有的文件
            # Class_Folder2 = os.path.join('%s\%s' % (Save_Folder, SA_Vector[k]))
            # Save_Path = os.path.join('%s\%s' % (Class_Folder2, CF_Tensor[p]))
            # cv2.imwrite(Save_Path, crop_img)

            titles = [u'去噪后图像', u'K-means聚类后', u'二值化处理', u'开运算', u'定位目标区域', u'切割后的图像']
            images = [original_img, pic_k, thresh, opened, draw_img, crop_img] #
            for i in range(6):
                plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
                plt.title(titles[i])
                plt.xticks([]), plt.yticks([])
            plt.show()
            cv2.waitKey(20180407)

walk()

结果展示如下:

k-means聚类及目标区域切割
图像K-means分割及目标区域切割

 

  • 10
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 23
    评论
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值