phân đoạn hình ảnh của hình ảnh RGB bởi K có nghĩa là phân cụm trong python


8

Tôi muốn phân đoạn hình ảnh RGB cho vùng đất bằng cách sử dụng k có nghĩa là phân cụm theo kiểu sao cho các vùng khác nhau của hình ảnh được đánh dấu bằng các màu khác nhau và nếu các ranh giới có thể được tạo sẽ tách các vùng khác nhau. Tôi muốn một cái gì đó như:

nhập mô tả hình ảnh ở đây

từ đây :

nhập mô tả hình ảnh ở đây

Có thể đạt được điều này bằng cách phân cụm K-nghĩa? Tôi đã tìm kiếm trên internet và nhiều hướng dẫn thực hiện bằng cách k phân cụm nhưng chỉ sau khi chuyển đổi hình ảnh sang thang màu xám. Tôi chỉ muốn làm điều đó với một hình ảnh RGB. Có nguồn nào có thể giúp tôi bắt đầu với nó không? Xin đề nghị một cái gì đó.


Xin chào, hãy thử liên kết này. Tôi đã thử nó một thời gian trước đây, nhưng chỉ có thành công hạn chế. Có lẽ bạn có thể làm cho nó hoạt động tốt hơn một chút. Chúc may mắn. opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/ Lời
Jcstay

Xin chào, cảm ơn vì lời đề nghị của bạn @Jcstay nhưng tôi đã thử liên kết và nó không giúp được gì. Cảm ơn bạn mặc dù.
rach

3
Tôi sẽ chỉ ra rằng thuật toán K-mean, giống như tất cả các phương pháp phân cụm khác, cần và sự phù hợp tối ưu của k. Vì mọi thứ trong dữ liệu tham chiếu sẽ được gán một lớp, nếu k không được tối ưu hóa, kết quả có thể bị sai mà không hỗ trợ cho lớp kết quả. Trong những trường hợp này, một lớp nhất định có thể không đại diện cho gì ngoài tiếng ồn hoặc hiệu ứng cận biên trong dữ liệu. Thông thường, giá trị hình bóng lề được sử dụng để chọn k tối ưu.
Jeffrey Evans

Câu trả lời:


9

Tôi đã hack cùng một giải pháp cho việc này và đã viết một bài viết trên blog về một chủ đề rất giống nhau, mà tôi sẽ tóm tắt ở đây. Kịch bản nhằm trích xuất một dòng sông từ hình ảnh NAIP 4 băng tần bằng cách sử dụng phương pháp phân loại và phân loại hình ảnh.

  1. Chuyển đổi hình ảnh thành một mảng numpy
  2. Thực hiện phân đoạn dịch chuyển nhanh (Hình 2)
  3. Chuyển đổi phân đoạn sang định dạng raster
  4. Tính toán NDVI
  5. Thực hiện thống kê khu vực trung bình bằng cách sử dụng các phân đoạn và NDVI để chuyển các giá trị NDVI sang các phân đoạn (Hình 3)
  6. Phân loại phân khúc dựa trên giá trị NDVI
  7. Đánh giá kết quả (Hình 4)

Ví dụ này phân đoạn một hình ảnh bằng cách sử dụng phân cụm quickshift trong không gian màu (x, y) với 4 dải (đỏ, lục, lam, NIR) thay vì sử dụng phân cụm K-nghĩa. Phân đoạn hình ảnh được thực hiện bằng cách sử dụng gói hình ảnh scikit . Chi tiết hơn về một loạt các thuật toán phân đoạn hình ảnh trong hình ảnh scikit ở đây . Để thuận tiện, tôi đã từng arcpythực hiện nhiều công việc của GIS, mặc dù điều này khá dễ dàng để chuyển sang GDAL.


nhập mô tả hình ảnh ở đây


from __future__ import print_function

import arcpy
arcpy.CheckOutExtension("Spatial")

import matplotlib.pyplot as plt
import numpy as np
from skimage import io
from skimage.segmentation import quickshift

# The input 4-band NAIP image
river = r'C:\path\to\naip_image.tif'

# Convert image to numpy array
img = io.imread(river)

# Run the quick shift segmentation
segments = quickshift(img, kernel_size=3, convert2lab=False, max_dist=6, ratio=0.5)
print("Quickshift number of segments: %d" % len(np.unique(segments)))

# View the segments via Python
plt.imshow(segments)

# Get raster metrics for coordinate info
myRaster = arcpy.sa.Raster(river)

# Lower left coordinate of block (in map units)
mx = myRaster.extent.XMin
my = myRaster.extent.YMin
sr = myRaster.spatialReference

# Note the use of arcpy to convert numpy array to raster
seg = arcpy.NumPyArrayToRaster(segments, arcpy.Point(mx, my),
                               myRaster.meanCellWidth,
                               myRaster.meanCellHeight)

outRaster = r'C:\path\to\segments.tif'
seg_temp = seg.save(outRaster)
arcpy.DefineProjection_management(outRaster, sr)

# Calculate NDVI from bands 4 and 3
b4 = arcpy.sa.Raster(r'C:\path\to\naip_image.tif\Band_4')
b3 = arcpy.sa.Raster(r'C:\path\to\naip_image.tif\Band_3')
ndvi = arcpy.sa.Float(b4-b3) / arcpy.sa.Float(b4+b3)

# Extract NDVI values based on image object boundaries
zones = arcpy.sa.ZonalStatistics(outRaster, "VALUE", ndvi, "MEAN")
zones.save(r'C:\path\to\zones.tif')

# Classify the segments based on NDVI values
binary = arcpy.sa.Con(zones < 20, 1, 0)
binary.save(r'C:\path\to\classified_image_objects.tif')

2
Đây là một giải pháp tuyệt vời và vượt qua một số vấn đề với phương tiện k và tìm kiếm một k tối ưu.
Jeffrey Evans

Điều này là rất tốt đẹp, công việc tuyệt vời !!
Jcstay

7

Bạn có thể nhìn vào cụm trong scikit-learn . Bạn sẽ cần đọc dữ liệu thành các mảng numpy (tôi muốn đề xuất rasterio ) và từ đó bạn có thể thao tác dữ liệu để mỗi dải là một biến để phân loại. Ví dụ, giả sử bạn có ba dải đọc vào python như red, greenbluemảng NumPy:

import numpy as np
import sklearn.cluster

original_shape = red.shape # so we can reshape the labels later

samples = np.column_stack([red.flatten(), green.flatten(), blue.flatten()])

clf = sklearn.cluster.KMeans(n_clusters=5)
labels = clf.fit_predict(samples).reshape(original_shape)

import matplotlib.pyplot as plt

plt.imshow(labels)
plt.show()

Lưu ý rằng phân cụm KMeans không tính đến kết nối trong tập dữ liệu.


+1 Câu trả lời tuyệt vời. Sẽ rất tuyệt khi trình bày một ví dụ về việc chuyển đổi hình ảnh màu sang mảng numpy bằng cách sử dụng rasterio;)
Aaron

1
@Aaron Cảm ơn! Tôi đã đăng một ví dụ dài hơn một chút bao gồm cả việc đọc dữ liệu bằng cách sử dụng rasterio.
om_henners

@om_henners giải pháp của bạn thật tuyệt vời nhưng tôi có một câu hỏi. Hình ảnh được phân đoạn được trả về bởi chương trình của bạn bằng cách sử dụng k có nghĩa là phân cụm là 2D. Bây giờ tôi cần tính hệ số tương tự xúc xắc giữa hình ảnh gốc (hình ảnh 3D trước khi chia thành các dải R, G, B) và hình ảnh được phân đoạn nhưng điều đó cần cả hai có cùng kích thước. Làm thế nào để tôi giải quyết vấn đề này?
rach
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.