opencv学习笔记9:根据图片颜色分割图像

根据图片颜色分割图像

程序目的

有一张图片,底色是蓝色的,感兴趣的区域是灰色的,需要对图片按颜色分割。

事实上按颜色分割图片在HSV通道上分割效果要远远优于在BGR通道上分割,如何获取某种颜色的HSV值大家请参考我的上篇博客。

程序思路:

读取图片(BGR)->转化到HSV空间->去除底色->获取感兴趣区域坐标->在原图上标记感兴趣区域

我有一批图片,底色是蓝色,感兴趣的区域是灰色,现在要将灰色区域分割出来,图片如下:
opencv学习笔记9:根据图片颜色分割图像_第1张图片
最终处理结果如下图,可以看到底色与感兴趣区域完全分离
opencv学习笔记9:根据图片颜色分割图像_第2张图片
单张图片分割的效果如下(绿色是程序分割出来的感兴趣区域,可以看到分割效果不错):
opencv学习笔记9:根据图片颜色分割图像_第3张图片
由于最近比较忙就不一步步讲解,直接根据程序思路上代码,代码简单有注释,应该比较好看懂

下面是单张图片的处理代码

#encoding:utf-8		
import numpy as np
import cv2
#   读 取 图 片
img = cv2.imread('/home/lqy/Data/lv/漏底20180901091938对照样本.jpg')  # 直接读为灰度图像
#   缩小图像10倍(因为我的图片太大,所以要缩小10倍方便看看效果)
height, width = img.shape[:2]
size = (int(width * 0.1), int(height * 0.1))  # bgr
img = cv2.resize(img, size, interpolation=cv2.INTER_AREA)
#BGR转化为HSV
HSV=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
cv2.imshow("imageHSV",HSV)
cv2.imshow('image',img)
color = [
    ([80, 0,0], [100, 255, 255])  # 蓝色范围~这个是我自己试验的范围,可根据实际情况自行调整~注意:数值按[b,g,r]排布
]
# 如果color中定义了几种颜色区间,都可以分割出来
for (lower, upper) in color:
    # 创建NumPy数组
    lower = np.array(lower, dtype="uint8")  # 颜色下限
    upper = np.array(upper, dtype="uint8")  # 颜色上限
    # 根据阈值找到对应颜色
    mask = cv2.inRange(HSV, lower, upper)    #查找处于范围区间的
    mask = 255-mask                          #留下铝材区域
    output = cv2.bitwise_and(img, img, mask=mask)    #获取铝材区域
    #bgroutput = cv2.cvtColor(output,cv2.COLOR_HSV2BGR)
    # 展示图片
    cv2.imshow("images", np.hstack([img, output]))
    im2, contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    print(mask.shape)
    #print(mask[0])
    print(len(contours))
    cv2.drawContours(img, contours, -1, (0, 0, 255), 1)
    for i in contours:
        print(cv2.contourArea(i))  # 计算缺陷区域面积
        x, y, w, h = cv2.boundingRect(i)  # 画矩形框
        cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 1)
    #cv.imwrite(show_result_path, match_img_color)
    cv2.imshow("detect",img)
    cv2.imshow("chanle", img)
    cv2.waitKey(0)
cv2.waitKey(0)

由于我要批量处理,下面是对整个文件夹的处理代码

#encoding:utf-8
import numpy as np
import cv2
import os
# 遍历指定目录,显示目录下的所有文件名
def eachFile(filepath):
    pathDir = os.listdir(filepath)
    child_file_name = []
    full_child_file_list = []
    for allDir in pathDir:
        child = os.path.join('%s%s' % (filepath, allDir))
        #child = child.decode('gbk') # .decode('gbk')是解决中文显示乱码问题
        full_child_file_list.append(child)
        child_file_name.append(allDir)
    return full_child_file_list, child_file_name


def mkdir(path):  # 判断是否存在指定文件夹,不存在则创建
    # 引入模块
    import os
    # 去除首位空格
    path = path.strip()
    # 去除尾部 \ 符号
    path = path.rstrip("\\")
    # 判断路径是否存在
    # 存在     True
    # 不存在   False
    isExists = os.path.exists(path)
    # 判断结果
    if not isExists:
        # 如果不存在则创建目录
        # 创建目录操作函数
        os.makedirs(path)
        print('mkdir' + path)
        return True
    else:
        return False

img_dir = '/home/lqy/Data/lv/'
new_img_dir = '/home/lqy/Data/processlv/'
mkdir(new_img_dir)
full_child_file_list, child_file_name = eachFile(img_dir)
for num,imgName in enumerate(full_child_file_list):

    newImgName = new_img_dir + child_file_name[num]
    img = cv2.imread(imgName )  # 直接读为灰度图像
    #BGR转化为HSV
    HSV=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
    color = [
    ([80, 0,0], [100, 255, 255])  # 蓝色范围~这个是我自己试验的范围,可根据实际情况自行调整~注意:数值按[b,g,r]排布
]
# 如果color中定义了几种颜色区间,都可以分割出来
    for (lower, upper) in color:
        # 创建NumPy数组
        lower = np.array(lower, dtype="uint8")  # 颜色下限
        upper = np.array(upper, dtype="uint8")  # 颜色上限
        # 根据阈值找到对应颜色
        mask = cv2.inRange(HSV, lower, upper)    #查找处于范围区间的
        mask = 255-mask                          #留下铝材区域
        output = cv2.bitwise_and(img, img, mask=mask)    #获取铝材区域
        #bgroutput = cv2.cvtColor(output,cv2.COLOR_HSV2BGR)
        # 展示图片
        #cv2.imshow("images", np.hstack([img, output]))
        im2, contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        #print(mask.shape)
        #print(mask[0])
        #print(len(contours))
    #cv2.drawContours(img, contours, -1, (0, 0, 255), 1)
    #for i in contours:
        #print(cv2.contourArea(i))  # 计算缺陷区域面积
    #x, y, w, h = cv2.boundingRect(contours[0])  # 画矩形框
    #print((contours[0]))
    maxArea = 0
    for numcontours, contour in enumerate(contours):
        if (cv2.contourArea(contour )>maxArea):
            maxArea = cv2.contourArea( contour )
            x, y, w, h = cv2.boundingRect(contour)

    img1 = img[y:y+h,x: x+ w]
    print(x)
    #cv2.drawContours(img, contours, -1, (0, 0, 255), 10)
    #cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 10)
    #cv.imwrite(show_result_path, match_img_color)
    #cv2.imshow("detect",img)
    #cv2.waitKey(0)
    cv2.imwrite(newImgName,img1)


你可能感兴趣的:(opencv,opencv学习笔记)