zoukankan      html  css  js  c++  java
  • 标识多个物体并返回物体中心坐标方法的实现

    概述

    在图像处理时,可能不可避免的需要计算图像中目标体的中心点,因而本片文章重点讲如何用传统图像处理方式来计算图像中目标体的中心。

    方案

    刚开始在考虑这个问题时其实也考虑了很多方法,比如找出物体最大坐标与最小坐标然后取平均值、直接求平均值等。这些方法比较容易想到但有一定的局限性,比如只能用在几何规则的图形上边,比如矩形、圆形等。但实际的目标体可能具有各种各样的形状,因而应用范围可能大大的受到限制。

    最终在查阅相关资料后采用的方式是求边缘+对边缘求中心点

    具体思路如下:

    1. 首先计算出图像目标体的边缘,当前已经有许多成熟的计算方法,为了提高计算速度,我们在计算边缘时,只需要边缘点即可,具体的边缘轮廓并不需要。
    2. 求出边缘点之后,可以求出边缘点的中心距进而求出中心点的坐标。

    结合我们工程上的实际应用场景:

    我们在项目中需要计算的图片如下所示:

    image-20201227144730843

    图片中有多个目标体,因而需要分不同的情况对多个目标体分别计算。

    在计算的过程中为了减少其他目标体的干扰,会做一个像素替换工作,比如在计算主体时只保留主体的像素,其他像素都变成0。

    然后求出主体的边缘,进而求出目标的中心。

    在求目标的中心时,为了提高计算速度,我们使用了一个OpenCV求中心距的函数:moments()

    中心矩

    openCV提供moments()函数来计算图像的中心矩,最高计算到三阶

    空间矩本质上是面积或者质量,因此可以通过一阶矩来计算中心:

    代码

    import imutils
    import datetime
    import cv2
    import numpy as np
    
    def getCenter(image, pixel):
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  # 灰度
        gray = np.where(gray==pixel,240,0)
        gray = np.asarray(gray,dtype='uint8')
        blurred = cv2.medianBlur(gray,5,0)
        # 在阈值图像中查找轮廓
        cnts = cv2.findContours(blurred.copy(), cv2.RETR_EXTERNAL,
                                cv2.CHAIN_APPROX_SIMPLE)
        # 找到白色对应的边界点的集合
        cnts = imutils.grab_contours(cnts)
        results = []
        # 计算轮廓中心
        for c in cnts:
            M = cv2.moments(c)
            # 防止出现除以0异常
            if  M["m00"] == 0:
                continue
            cX = int(M["m10"] / M["m00"])
            cY = int(M["m01"] / M["m00"])
            # 在图像上绘制形状的轮廓和中心
            # cv2.drawContours(image, [c], -1, (0, 255, 0), 2)
            # cv2.circle(image, (cX, cY), 3, (72, 61, 139), -1)
            # cv2.putText(image, "center", (cX - 20, cY - 20),
            #             cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)
            results.append([cX,cY])
        return results
    def getObjectCenter(image_path):
        image = cv2.imread(image_path)
        # 只考虑图片上有一架无人机
        loadCenterList = getCenter(image,240)
        roterCenterList = getCenter(image,80)
        bodayCenterList = getCenter(image,160)
        # 获取唯一负载
        loadCenter = []
        bodayCenter = []
        if len(loadCenterList) >=1:
            loadCenter = loadCenterList[len(loadCenterList) - 1]
            cv2.circle(image, (loadCenter[0], loadCenter[1]), 5, (128, 225, 0), -1)
        # 获取主体中心坐标(修正前)
        if len(bodayCenterList) >=1:
            bodayCenter = bodayCenterList[len(bodayCenterList) - 1]
        # 画出主体坐标
        if bodayCenter !=[]:
            # 对坐标进行简单修正
            if loadCenter != []:
                bodayCenter[1] -= int((abs(loadCenter[1] - bodayCenter[1])) * 0.5)
            cv2.circle(image, (bodayCenter[0], bodayCenter[1]), 5, (0, 225, 118), -1)
        # 画出旋翼中心
        for roterCenter in roterCenterList:
            cv2.circle(image, (roterCenter[0], roterCenter[1]), 5, (168, 0, 108), -1)
        return image
    

    结果

    image-20201227144523255

  • 相关阅读:
    Navicat Premium 12连接Oracle时提示oracle library is not loaded的问题解决
    事务传播机制Propagation.REQUIRES_NEW
    @ApiImplicitParams、ApiImplicitParam的使用
    启动微服务项目的时候报redisInit错误---本地启动redis服务
    Swagger介绍及使用
    mybaitis框架-trim标签
    pgadmin怎样创建新的连接
    微服务项目启动
    管理中第一可怕之事(2) . 分类: 项目管理 2014-06-25 18:54 257人阅读 评论(0) 收藏
    管理中第一可怕之事(1) . 分类: 项目管理 2014-06-25 18:53 264人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/goWithHappy/p/find-center-of-image.html
Copyright © 2011-2022 走看看