opencv轮廓围的面积_滴水湖水域面积测算

        这两天的上海自贸区临港新片区的发布使临港成为这几天的热点,可以说是让临港由上海死角摇身一变为投资热土,作为一个在临港生活和工作的居民感觉备受鼓舞,有必要写点关于临港的东西,想来想去最后就决定写临港的大地标滴水湖吧。

81e97f8653acc0c4b0fddacd5228515d.png

        滴水湖位于临港主城区的核心位置,是一个直径为2.6公里的正圆形湖,而环滴水湖的一/二/三/沪城环路也都为正圆形,有六条大道和一条入海河呈放射状向滴水湖四周发散,路与路之间夹角为标准的45度(作为强迫症患者想不清楚为啥规划图中正北向的浦港大道被弄没了..)。湖边规划非常工整,风景秀丽让人心旷神怡,而我的家就安在滴水湖畔,没事去湖边坐坐也可以度过一段时光,作为一个Runner经常没事绕湖跑个一两圈,对这个湖就分外有感情。

        下面说说我今天要做的事情,下图是从地图上截取的滴水湖地图,我们要测算环湖一路内包含的水域面积。

68558fdf0677f463e824fb4cff963d58.png

        从上图可以看出在滴水湖中央有三个岛,皇冠酒店所在的南岛为不规则形,而娱乐之岛-西岛为一个近似长方形,而荒芜的北岛像是一条尾巴朝向湖中央的丑鱼。

        本文中我打算使用最近初学的opencv来测算刨除三个岛以及岸边的不规则绿化带剩下的蓝色水域面积,思路为使用opencv划出湖水的边界,按照颜色做轮廓提取,然后通过像素点比例计算湖水所占面积,解决方案如下图所示。

        首先画个圆选定滴水湖我们要检测的部分,这个步骤通过霍夫变换圆检测方法来实现:

import cv2import numpy as np#图片读取img = cv2.imread("dishuilake.png")# 把图片转换为灰度模式gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#霍夫变换圆检测circles= cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 100, param1=150, param2=50, minRadius=5, maxRadius=500)# 输出霍夫变换圆检测的返回值print('霍夫变换圆检测的信息:\n', circles)# 输出检测到圆的个数print('圆的个数为%d个.'%len(circles[0]))x, y, r = 0, 0, 0output = img.copy()#根据检测到圆的信息,画出每一个圆for circle in circles[0]:    #坐标行列    x=int(circle[0])    y=int(circle[1])    #半径    r=int(circle[2])    # 圆的基本信息    print('圆的中心为(%s, %s), 半径为%s.' % (x, y, r))    #在原图用指定颜色标记出圆的位置    output = cv2.circle(output, (x,y), r, (0,0,255), 1)    breakcircle_pixes = 0# 去除圆以外的部分for a in range(output.shape[0]):    for b in range(output.shape[1]):        if ((a - x) **2 + (b -y)**2 > r**2):            output[a, b] = [255, 255, 255]        else:            # 统计园内总pix数量            circle_pixes += 1else:    print("circle_pixes:%s" % circle_pixes)#显示新图像cv2.imshow("captured", np.hstack([img, output]))# 图像输出cv2.imwrite('captured.png',output)#按任意键退出cv2.waitKey(0)cv2.destroyAllWindows()

        我们就得到了这样一张裁剪之后的图,这个图正好是环湖一路以内部分,同时获得圆的中心为(453, 460), 半径为421,像素点个数circle_pixes:556769:

0708edd8c8c0cec4a165269dade22a3a.png

        然后取图中湖水的颜色:

import cv2#图片读取,将图像转化为ndarray数组img = cv2.imread("captured.png")print(img.shape)# 输出为(908, 910, 3),目测其中间点位置为湖水,则取(454,455)组的元素print(img[454,455]) # 输出为[254 199 175],其为湖水的颜色

        然后按照颜色划出水域部分的轮廓:

import cv2import numpy as np#图片读取img = cv2.imread("captured.png")# 定义颜色边界 (lower[r,g,b], upper[r,g,b])lower, upper = ([254, 199, 175], [254, 199, 175])# 将颜色边界转成numpy数组lower = np.array(lower, dtype='uint8')upper = np.array(upper, dtype='uint8')#在指定边界内查找颜色并应用掩码mask = cv2.inRange(img, lower, upper)# 进行与操作output = cv2.bitwise_and(img, img, mask=mask)# 显示结果cv2.imshow("images", np.hstack([img, output]))cv2.waitKey(0)# 图像输出cv2.imwrite('result.png',output)cv2.destroyAllWindows()

这个变换步骤我们从左图的圆形区域得到了右图的水域部分,水域部分像素点laker_pixes:435600

5355b1923aea873119de4b1692ae9796.png

    我们算得了水域部分的像素点数量为  435600个,圆内像素点个数556769个,水域部分占整个圆形内的78.23%,加上我们已得知滴水湖直径为2.6公里,则水域面积应该为3.14*1.3**2*0.7823 = 4.15平方公里,这就是最终我们要的结果。

    总结:本文我们通过opencv使用了简单的图形变换的一些功能,最终得到了我们想要的效果,希望滴水湖以后能越来越美,同时欢迎大家多来滴水湖玩。

40b66140f1b8ba08d54c753eed4a9f7e.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值