当前位置:   article > 正文

c4.5算法python实现_结合python与遥感图像的区域生长算法实现

pythonc4.5算法案例运用

2dd1266cc5b825861d860aa76be5868c.png

引言

本文章将带大家实现灾害监测中一种常用的图像分类方法,即区域生长算法。与前面介绍的几种图像分割方法不同,区域生长算法可直接对高于Uint8灰级的数据直接进行处理,所以保持了原数据的结构形式。另外,区域生长算法涉及到的参数较多,分类的结果与参数关联度较高,所以笔者也添加了阈值参量的调试程序。

代码实现流程

  • 多波段TIF图像转jpg图像
  • 输入jpg图像,查询目标种子坐标
  • 区域生长算法最优阈值调试
  • 分割结果输出

基本原理

区域生长算法是将图像中所有种子附近的像素按照像元值的相似度和似然性进行合并、归类的二值化过程。区域生长算法的生长准则包括四邻域和八邻域两种。除了生长准则外,图像中种子点的位置与个数也与分类结果紧密相关。关于种子点的选择方式也有两种,分别是手动选点和自动选点,鉴于本文的数据量与分割精度,笔者采用了自动选点方式(其实,手动选点精度会更高一些)。

af0b467cfac2a972e2d9c4899e2eb277.png
8邻域生长准则

数据介绍

上官:基于Python的遥感图像NDVI批处理​zhuanlan.zhihu.com
aa5673e94d7066040af79f054fc390b0.png

Python代码实现(jpg图像转换)

  1. import cv2
  2. import gdal
  3. import numpy as np
  4. def image_open(image):
  5. data = gdal.Open(image)
  6. if data == "None":
  7. print("数据无法打开")
  8. return data
  9. Filepath = r"E:yynctryedata20180911_yync(DA).tif"
  10. data = image_open(Filepath).ReadAsArray().transpose(1, 2, 0)
  11. data1 = data[:, :, 0:3]
  12. Normalize_data = np.zeros(data1.shape)
  13. for d in range(data1.shape[2]):
  14. for i in range(data1.shape[0]):
  15. for j in range(data1.shape[1]):
  16. Normalize_data[i][j][d] = (data1[i][j][d] - np.min(data1)) / (np.max(data1) - np.min(data1))
  17. Normalize_data = Normalize_data*256
  18. data2 = Normalize_data.astype(np.uint8)
  19. # data = image_open(Filepath).ReadAsArray()
  20. # data1 = data[0:3, :, :].transpose(1, 2, 0)
  21. # data2 = data1.astype(np.uint8)
  22. cv2.imwrite(r"E:yynctryedata20180911_yync(DA)1.jpg", data2)

代码关键点说明:

这段代码的主要过程是将多波段图像的BGR波段合成了RGB真彩色图像,目的是根据图像获取需要的种子点坐标。笔者采用了遍历+归一化的方法进行图像转换。这里需要说明的一点是传统印象里,要实现图像的格式转换和数据压缩可能只需要用numpy的astype方法就可以实现,也就是下面这段代码:

  1. # data = image_open(Filepath).ReadAsArray()
  2. # data1 = data[0:3, :, :].transpose(1, 2, 0)
  3. # data2 = data1.astype(np.uint8)

经过笔者的亲测试验这种方法不可行,至少对于本文章所使用的数据是不可行的,到底有多么的不可行呢?大家看看下图吧。虽然图(b)的显示仍有问题,但效果比图(a)好的不是一点半点。

ce3fde9912fac854039daf7c77a9c6f7.png
(a)为注释代码运行结果 ,(b)为归一化方式运行结果

Python代码实现(坐标查询)

  1. import cv2
  2. import gdal
  3. def image_open(image):
  4. data = gdal.Open(image)
  5. if data == "None":
  6. print("数据无法打开")
  7. return data
  8. def on_EVENT_LBUTTONDOWN(event, x, y, flags, param):
  9. if event == cv2.EVENT_LBUTTONDOWN:
  10. xy = "%d,%d" % (x, y)
  11. cv2.circle(img, (x, y), 1, (255, 0, 0), thickness = -1)
  12. cv2.putText(img, xy, (x, y), cv2.FONT_HERSHEY_PLAIN,
  13. 1.0, (0,0,0), thickness = 1)
  14. cv2.imshow("image", img)
  15. img = cv2.imread(r"E:yynctryedata20180911_yync(DA)1.jpg")
  16. cv2.namedWindow("image")
  17. cv2.setMouseCallback("image", on_EVENT_LBUTTONDOWN)
  18. while(1):
  19. cv2.imshow("image", img)
  20. if cv2.waitKey(0)&0xFF==27:
  21. break
  22. cv2.destroyAllWindows()

代码关键点说明:

把之前的图像输入进来并运行之后,会展示出图像,此时只需要点击图像中的像素位置即可显示矩阵坐标信息。

0040e74b72b1a18602a177032e312c0f.png

Python代码实现(参数搜索)

  1. import numpy as np
  2. import cv2
  3. import gdal
  4. class Point(object):
  5. def __init__(self, x, y):
  6. self.x = x
  7. self.y = y
  8. def getX(self):
  9. return self.x
  10. def getY(self):
  11. return self.y
  12. def image_open(image):
  13. data = gdal.Open(image)
  14. if data == "None":
  15. print("数据不存在")
  16. return data
  17. def getGrayDiff(img, currentPoint, tmpPoint):
  18. return abs(int(img[currentPoint.x, currentPoint.y]) - int(img[tmpPoint.x, tmpPoint.y]))
  19. def selectConnects(p):
  20. if p != 0:
  21. connects = [Point(-1, -1), Point(0, -1), Point(1, -1), Point(1, 0), Point(1, 1),
  22. Point(0, 1), Point(-1, 1), Point(-1, 0)]
  23. else:
  24. connects = [Point(0, -1), Point(1, 0), Point(0, 1), Point(-1, 0)]
  25. return connects
  26. def regionGrow(img, seeds, thresh, p=1):
  27. height, weight = img.shape
  28. seedMark = np.zeros(img.shape)
  29. seedList = []
  30. for seed in seeds:
  31. seedList.append(seed)
  32. label = 1
  33. connects = selectConnects(p)
  34. while (len(seedList) > 0):
  35. currentPoint = seedList.pop(0)
  36. seedMark[currentPoint.x, currentPoint.y] = label
  37. for i in range(8):
  38. tmpX = currentPoint.x + connects[i].x
  39. tmpY = currentPoint.y + connects[i].y
  40. if tmpX < 0 or tmpY < 0 or tmpX >= height or tmpY >= weight:
  41. continue
  42. grayDiff = getGrayDiff(img, currentPoint, Point(tmpX, tmpY))
  43. if grayDiff < thresh and seedMark[tmpX, tmpY] == 0:
  44. seedMark[tmpX, tmpY] = label
  45. seedList.append(Point(tmpX, tmpY))
  46. return seedMark
  47. def regionGrow_t(t):
  48. thresh = t
  49. binary_image = regionGrow(img, seeds, thresh, p=1) #p=0四邻域,p≠0八邻域
  50. cv2.imshow("thresh_test", binary_image)
  51. #选取图像中适于分类的敏感波段
  52. Filepath = r"E:yynctryedata20180911_yync(DA).tif"
  53. img = image_open(Filepath).ReadAsArray()
  54. img = img[1, :, :]
  55. print(img.shape)
  56. #设定种子
  57. seeds = [Point(163,79),Point(173,127),Point(184,15),
  58. Point(73,144),Point(85,199)]
  59. thresh = 10
  60. cv2.namedWindow("thresh_test")
  61. #设定调试的阈值范围
  62. cv2.createTrackbar('thresh', "thresh_test", 1, 30, regionGrow_t)
  63. #调试可视化
  64. while(1):
  65. k = cv2.waitKey(1)&0xFF
  66. if k==27:
  67. break
  68. thresh = cv2.getTrackbarPos('thresh',"thresh_test")

代码关键点说明:

这段代码调试的是生长规则判定过程中的阈值,移动阈值选项卡就可以查看不同阈值下的分割结果,另外阈值范围大家可以自己调试。这里,我们选择27作为最优的阈值。

b29f28f2586eb70e5f6bc236f695f917.png

Python代码实现(结果输出)

  1. import gdal
  2. import numpy as np
  3. import cv2
  4. def image_open(image):
  5. data = gdal.Open(image)
  6. if data == "None":
  7. print("数据不存在")
  8. return data
  9. def datasave(Filename, data):
  10. output1 = gdal.GetDriverByName("GTiff")
  11. output2 = output1.Create(Filename, width, height, 1, gdal.GDT_Float32)
  12. output2.SetProjection(projection)
  13. output2.SetGeoTransform(transform)
  14. output2.GetRasterBand(1)
  15. output2.WirteArray(data)
  16. class Point(object):
  17. def __init__(self, x, y):
  18. self.x = x
  19. self.y = y
  20. def getX(self):
  21. return self.x
  22. def getY(self):
  23. return self.y
  24. def getGrayDiff(img, currentPoint, tmpPoint):
  25. return abs(int(img[currentPoint.x, currentPoint.y]) - int(img[tmpPoint.x, tmpPoint.y]))
  26. def selectConnects(p):
  27. if p != 0:
  28. connects = [Point(-1, -1), Point(0, -1), Point(1, -1), Point(1, 0), Point(1, 1),
  29. Point(0, 1), Point(-1, 1), Point(-1, 0)]
  30. else:
  31. connects = [Point(0, -1), Point(1, 0), Point(0, 1), Point(-1, 0)]
  32. return connects
  33. def regionGrow(img, seeds, thresh, p=1):
  34. height, weight = img.shape
  35. seedMark = np.zeros(img.shape)
  36. seedList = []
  37. for seed in seeds:
  38. seedList.append(seed)
  39. label1 = 255
  40. connects = selectConnects(p)
  41. while (len(seedList) > 0):
  42. currentPoint = seedList.pop(0)
  43. seedMark[currentPoint.x, currentPoint.y] = label1
  44. for i in range(8):
  45. tmpX = currentPoint.x + connects[i].x
  46. tmpY = currentPoint.y + connects[i].y
  47. if tmpX < 0 or tmpY < 0 or tmpX >= height or tmpY >= weight:
  48. continue
  49. grayDiff = getGrayDiff(img, currentPoint, Point(tmpX, tmpY))
  50. if grayDiff < thresh and seedMark[tmpX, tmpY] == 0:
  51. seedMark[tmpX, tmpY] = label1
  52. seedList.append(Point(tmpX, tmpY))
  53. return seedMark
  54. #数据读取及参数设定
  55. Filepath = r"E:yynctryedata20180911_yync(DA).tif"
  56. Filename1 = r"E:yynctryedataquyushengzhang.jpg"
  57. data = image_open(Filepath)
  58. width = data.RasterXSize
  59. height = data.RasterYSize
  60. projection = data.GetProjection()
  61. transform = data.GetGeoTransform()
  62. data1 = data.GetRasterBand(2)
  63. img = data1.ReadAsArray(0, 0, width, height)
  64. result1 = np.zeros(img.shape)
  65. #设定种子
  66. seeds = [Point(163,79),Point(173,127),Point(184,15),
  67. Point(73,144),Point(85,199)]
  68. #输入调试得到的最优阈值
  69. binaryImg = regionGrow(img, seeds, 27).astype(np.uint8)
  70. cv2.imwrite(Filename1, binaryImg)
  71. cv2.imshow("image", binaryImg)
  72. cv2.waitKey(0)

代码关键点说明:

图像输出是不带坐标的结果,大家可以在相关软件里附上坐标,或者在gdal库里进行处理

处理结果

个人感觉比之前的阈值分割方法好很多,四邻域的生长准则大家可以自行试下。

29cf35bf5bb9915cc722150e22ff6b41.png

参考文献

https://www.baidu.com/link?url=nDGUC3UosIhcqMdDd9ZEISw4k7OTVdTy7QSR6vXyZ5hcRBcPEc0J8dEN86TB-xV214fUDTgPSRGfpYsIo2zUgykmlhOXWOzW8Ljk4w0_9HS&wd=&eqid=fb0114a80003d04a000000025efae5cd​www.baidu.com 区域生长算法原理及实现_小武的博客-CSDN博客_区域生长算法​blog.csdn.net
dc37d35a31e94bd582a9a26efdb28ca4.png
区域生长算法 全局分类 C++ & matlab​www.cnblogs.com
f689cd69ba46d3b76ffdb2b8881867a5.png
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/398792
推荐阅读
相关标签
  

闽ICP备14008679号