opencv图像处理分离出蓝色物体(借鉴+理解)

# -*- coding: utf-8 -*-


import cv2
import numpy as np
#import matplotlib.pyplot as plt
# 使用2b-g-r分离
 
src = cv2.imread('E:\chenhu.jpg')#imread是计算机语言中的一个函数,用于读取图片文件中的数据。
#print(src)
#cv2.imshow('src', src)
 
# 转换为浮点数进行计算
fsrc = np.array(src, dtype=np.float32) /255.0#转化成np
print(fsrc)
(b,g,r) = cv2.split(fsrc)
print(b)
gray = 2*b-g-r#灰度图
#gray = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)
# 求取最大值和最小值
(minVal, maxVal, minLoc, maxLoc) = cv2.minMaxLoc(gray)
#参数1:InputArray类型的src,输入单通道数组(图像)。
#参数2:double*类型的minVal,返回最小值的指针。若无须返回,此值置为NULL。
#参数3:double*类型的maxVal,返回最大值的指针。若无须返回,此值置为NULL。
#参数4:Point*类型的minLoc,返回最小位置的指针(二维情况下)。若无须返回,此值置为NULL。
#参数5:Point*类型的maxLoc,返回最大位置的指针(二维情况下)。若无须返回,此值置为NULL。
#参数6:InputArray类型的mask,用于选择子阵列的可选掩膜。
# 转换为u8类型,进行otsu二值化
gray_u8 = np.array((gray - minVal) / (maxVal - minVal) * 255, dtype=np.uint8)#公式
(thresh, bin_img) = cv2. threshold(gray_u8, -1.0, 255, cv2.THRESH_OTSU)#二值化,返回值有问题
#用threshold()函式,使用方式也一樣,只是最後一個參數增加CV_THRESH_OTSU,目前otsu只能使用在8位元圖。
#type:二值化操作型態,共有THRESH_BINARY、THRESH_BINARY_INV、THRESH_TRUNC、THRESH_TOZERO、THRESH_TOZERO_INV五種。
#type從上述五種結合CV_THRESH_OTSU,類似寫成:THRESH_BINARY | CV_THRESH_OTSU
#简单阈值当然是最简单,选取一个全局阈值,然后就把整幅图像分成了非黑即白的二值图像了。函数为cv2.threshold() 
#这个函数有四个参数,第一个原图像,第二个进行分类的阈值,
#第三个是高于(低于)阈值时赋予的新值,第四个是一个方法选择参数,常用的有: 
cv2.imshow('bin_img', bin_img)
cv2.waitKey(0)
cv2.destroyAllWindows()#任意按键继续
# 获取轮廓,我们的目的是分块,因此只使用外层轮廓,使用点序列的形式


bin_img_save = np.copy(bin_img)
# cv2.RETR_LIST, cv2.RETR_TREE, cv2.RETR_CCOMP, cv2.RETR_EXTERNAL
bin_img_save,contours, hierarchy= cv2.findContours(bin_img_save,cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
#第一个它返回了你所处理的图像
#第二个,正是我们要找的,轮廓的点集
#第三个,各层轮廓的索引
# 按面积排序
areas = np.zeros( len(contours) )#都是0
idx = 0
for cont in contours : #索引中的
    areas[idx] = cv2.contourArea(cont)#https://blog.csdn.net/m0_37914500/article/details/78615284
    idx = idx + 1
areas_s = cv2.sortIdx(areas, cv2.SORT_DESCENDING | cv2.SORT_EVERY_COLUMN)#对矩阵的每列按照降序排列
#cv::sortIdx 负责返回对应原矩阵的索引。
#CV_SORT_EVERY_ROW + CV_SORT_ASCENDING:对矩阵的每行按照升序排序;
#CV_SORT_EVERY_ROW + CV_SORT_DESCENDING:对矩阵的每行按照降序排序;
#CV_SORT_EVERY_COLUMN + CV_SORT_ASCENDING:对矩阵的每列按照升序排序;
#CV_SORT_EVERY_COLUMN + CV_SORT_DESCENDING:对矩阵的每列按照降序排序;
#opencv的sort函数是将图像进行排序,可以根据列或者行,按照升序或者降序对矩阵进行重新排序,如果想将整个图像进行排序,则可以:
#Mat flat; tmpsplit; 
#tmpsplit.reshape(1,1).copyTo(flat); 
#cv::sort(flat,flat,CV_SORT_EVERY_ROW + CV_SORT_ASCENDING);
#另外,opencv还有另外一个函数:sortIdx 
#该函数与sort的区别在与,sortIdx还会保存排序像素值原始的位置信息


(b8, g8, r8) = cv2.split(src)#分通道
# 对每个区域进行处理
for idx in areas_s :
    if areas[idx] < 100 :
        break
 
    # 绘制区域图像,通过将thickness设置为-1可以填充整个区域,否则只绘制边缘
    poly_img = np.zeros( bin_img.shape, dtype = np.uint8 )
    cv2.drawContours(poly_img, contours, idx, [255,255,255], -1)
   # cv2.findContours()函数来查找检测物体的轮廓。
    poly_img = poly_img & bin_img
 #opencv官方文档中给了一个样例,  就是利用drawContours 把 connected - components 都提取出来
    #cv::findContours(img,outerline,hierarchy,CV_RETR_TREE,CV_CHAIN_APPROX_NONE);
    #int idx = 0;
    #for( ; idx >= 0; idx = hierarchy[idx][0] ){
     #   cv::Scalar color( rand()&255, rand()&255, rand()&255 );
      #  cv::drawContours( imgEmpty, outerline, idx, color, CV_FILLED, 8, hierarchy );
   # }
    # 得到彩色的图像
    color_img = cv2.merge([b8 & poly_img, g8 & poly_img, r8 & poly_img])#
 
    cv2.imshow('poly_img', color_img)
    cv2.waitKey()

cv2.destroyAllWindows()

运行结果

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值