PIL利用投影分割图片数字(二)


#-*- coding: UTF-8 -*-     
import cv2
import numpy as np 
from matplotlib import pyplot as plt 
from PIL import Image,ImageDraw
import numpy as np
def first():
    """
    根据图片确定A4之的边缘,并裁切出A4纸部分
    
    """
    np.set_printoptions(threshold=np.inf)
    img=cv2.imread('test.jpg')
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
    contours, hierarchy = cv2.findContours(binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    print (len(contours))
    for i in range(0,len(contours)):
        x, y, w, h = cv2.boundingRect(contours[i])
        #cv2.rectangle(img, (x,y), (x+w,y+h), (153,153,0), 5)
    #cv2.imshow("img", img)
    #cv2.waitKey(0)
    #cv2.destroyWindow("img")
    newimage=img[y+5:y+h-5,x+40:x+w-30]
    cv2.imwrite( "output.jpg",newimage)

def shuiping(image_data):
    """首先传递参数,读取的灰度图片;
    随后,将图片二值化;接着进行水平投影;
    利用水平投影的最后位置,确认出切割图片的坐标。
    """
    image=image_data
    limit = 130
    table = []

    #二值化,阈值200以下全部变为为0,其余变为255
    for i in range(256):
        if i < limit:
            table.append(0)
        else:
            table.append(1)
    image= image.point(table, '1')
    #image.show()
    
    image= np.array(image)
    (h,w)=image.shape 
    a = [0 for z in range(0, h)]

    #水平投影,数组里的数字对应水平位置黑色区域像素点长度
    num =0 
    for j in range(0,h):  
        for i in range(0,w):
            if  image[j,i]==0:
                num+=1
                a[j]+=1 
                image[j,i]=255
    for j  in range(0,h):  
        for i in range(0,a[j]):   
            image[j,i]=0

    image=Image.fromarray(image)
    image.show()

    #水平投影最后会有结束点,结束点最后一个位置是黑色的,
    #对应数组不为0,白色位置对应数组位置全部为0
    x1=0
    y1=0
    y2=0
    x2=image.width
    list_pic=[]
    for i in range(len(a)):
        if a[i-1]==0 or a[i]!=0:
            y2+=1
        elif a[i-1]!=0 and a[i]==0:
            y2+=1
            list_pic.append([x1,y1,x2,y1+y2])
            y1=y1+y2
            y2=0 




    num=1
    pic_data=[]
    for i in list_pic:
        croping = image_data.crop(i)
        croping.save( "shuiping/"+str(num) + '.jpg')
        num+=1
        pic_data.append(croping)
            
    
    print("分割完成,已保存!")
    return pic_data

def chuizhi(image_data):
    """首先传递参数,读取的灰度图片;
    随后,将图片二值化;接着进行垂直投影;
    利用垂直投影的间断特点,确认出切割图片的坐标。
    """
    num=1
    count=1
    for pic in image_data:
        image=pic
        limit = 200
        table = []

        #二值化,阈值200以下全部变为为0,其余变为255
        for i in range(256):
            if i < limit:
                table.append(0)
            else:
                table.append(1)
        image= image.point(table, '1')
        image= np.array(image)
        
        (h,w)=image.shape
        print (h,w)

        #垂直投影,数组里的数字对应垂直位置黑色区域像素点长度
        b = [0 for z in range(0, w)] 
        for i in range(0,w):
            for j in range(0,h):
                if  image[j,i]==0:
                    b[i]+=1 
                    image[j,i]=255
        for i  in range(0,w):  
            for j in range(0,b[i]):   
                image[j,i]=0
        image=Image.fromarray(image)
        #image.show()
        x1=0
        x2=0
        y1=h
        y2=0
        list=[]

        #垂直投影最后会有结束点,结束点最后一个位置是黑色的,
        #对应数组不为0,白色位置对应数组位置全部为0
        for i in range(len(b)):
            if b[i-1]==0 or b[i]!=0:
                y2+=1
            elif b[i-1]!=0 and b[i]==0:
                y2+=1
                list.append([x1,x2,(x1+y2),y1-1])
                x1=x1+y2
                y2=0 
        
        for i in list:
            croping = pic.crop(i)
            croping.save( "chuizhi/"+str(num) + '.jpg')
            num+=1

        for i in list:
            draw=ImageDraw.Draw(pic)
            draw.rectangle(i)
          

        #pic.show()
        pic.save("rec"+ str(count)+".jpg")
        count+=1

    print("分割完成,已保存!")


def main():
    #first()
    img_path="test1.jpg"
    image_data=(Image.open(img_path).convert('L'))
    #image_data.show()
    pic=shuiping(image_data)
    chuizhi(pic)
main()

测试图片
在这里插入图片描述
输出结果:

在这里插入图片描述

在这里插入图片描述

说明:此图片是PS输出的照片,效果很好。手机拍摄的图片含有很多噪声,因此效果不好。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是分KMeans实现图片分割的Python代码: ```python import numpy as np from PIL import Image def load_image(path): img = Image.open(path) return np.array(img) def save_image(array, path): img = Image.fromarray(array) img.save(path) def distance(x, y): return np.sqrt(np.sum((x-y)**2)) def kmeans(points, k, max_iter=100): centers = points[np.random.choice(range(len(points)), k, replace=False)] for _ in range(max_iter): clusters = [[] for _ in range(k)] for point in points: distances = [distance(point, center) for center in centers] cluster = np.argmin(distances) clusters[cluster].append(point) new_centers = [] for i in range(k): new_center = np.mean(clusters[i], axis=0) new_centers.append(new_center) if np.allclose(centers, new_centers): break centers = new_centers return centers, clusters def binary_kmeans(image_path, k=2): image = load_image(image_path) points = np.reshape(image, (-1, 3)) centers, clusters = kmeans(points, k) labels = np.zeros(len(points), dtype=int) for i, cluster in enumerate(clusters): for point in cluster: labels[np.where((points == point).all(axis=1))] = i segmented_image = np.reshape(labels, (image.shape[0], image.shape[1])) return segmented_image if __name__ == '__main__': segmented_image = binary_kmeans('image.jpg', k=2) save_image(segmented_image, 'segmented_image.png') ``` 其中,`load_image`函数将图片读入为numpy数组,`save_image`函数将numpy数组保存为图片。`distance`函数计算两个点之间的欧氏距离。`kmeans`函数执行kmeans算法,返回聚类中心和每个点所属的聚类。`binary_kmeans`函数对图片进行分kmeans分割,返回分割后的值图像。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

佐倉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值