如何用opencv进行农田分类和面积计算呀?用纹理进行分类

用python语言,使用特征提取的方法分类,分类完成后进行面积计算

img

转自http://t.csdn.cn/2F7t6

# 轮廓/形状检测
import cv2
import numpy as np

# 图像排列处理函数
def stackImages(scale, imgArray):
    rows = len(imgArray)
    cols = len(imgArray[0])
    rowsAvailable = isinstance(imgArray[0], list)
    width = imgArray[0][0].shape[1]
    height = imgArray[0][0].shape[0]
    if rowsAvailable:
        for x in range(0, rows):
            for y in range(0, cols):
                if imgArray[x][y].shape[:2] == imgArray[0][0].shape[:2]:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
                else:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
                if len(imgArray[x][y].shape) == 2: imgArray[x][y] = cv2.cvtColor(imgArray[x][y], cv2.COLOR_GRAY2BGR)
        imageBlank = np.zeros((height, width, 3), np.uint8)
        hor = [imageBlank]*rows
        hor_con = [imageBlank]*rows
        for x in range(0, rows):
            hor[x] = np.hstack(imgArray[x])
        ver = np.vstack(hor)
    else:
        for x in range(0, rows):
            if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
                imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
            else:
                imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
            if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
        hor= np.hstack(imgArray)
        ver = hor
    return ver

def getContours(img):
    contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)  # 使用cv点查找轮廓(传入图像对象和检测范围参数)
    for cnt in contours:
        area = cv2.contourArea(cnt)
        print(area)
        if area > 500:  # 设置检测阈值
            cv2.drawContours(imgContour, cnt, -1, (255, 0, 0), 3)  # 将复制图像放上面,从而框出
            peri = cv2.arcLength(cnt, True)  # 计算周长(轮廓长度)检测外围轮廓
            # print(peri)
            approx = cv2.approxPolyDP(cnt, 0.02*peri, True)  # 统计拐点个数,通过拐点个数确认图形形状
            print(len(approx))  # 打印其长度,3是三角,4是长方形
            objCor = len(approx)  # 检测边界框
            x, y, w, h = cv2.boundingRect(approx)  # 得到xy和对象长宽

            # 对象类型名称设置:
            if objCor == 3:
                objectType = "Tri"
            elif objCor == 4:
                aspRatio = w/float(h)
                if aspRatio > 0.98 and aspRatio < 1.03:
                    objectType = "Square"
                else:
                    objectType = "Rectangle"
            elif objCor > 4:
                objectType = "Circles"
            else:
                objectType = "None"

            cv2.rectangle(imgContour, (x, y), (x+w, y+h), (0, 255, 0), 2)  # 绘制框,位置宽高(边界框)
            cv2.putText(imgContour, objectType,
                        (x+(w//2)-10, y+(h//2)-10), cv2.FONT_HERSHEY_COMPLEX, 0.7,
                        (0, 0, 0), 2)  # 设置脚本文字(进行了偏移),字体颜色,大小,颜色,粗细

path = '5.png'  # 设置资源文件夹
img = cv2.imread(path)
imgContour = img.copy()

# 预处理,转化为灰度,检测拐角点
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 频道为白色,BG设置为灰色
imgBlur = cv2.GaussianBlur(imgGray, (7, 7), 1)  # 高斯模糊函数,定义内核,设置sigma
imgCanny = cv2.Canny(imgBlur, 50, 50)  # 边缘检测器
getContours(imgCanny)

imgBlank = np.zeros_like(img)  # 创建空白图像
imgStack = stackImages(0.5, ([img, imgGray, imgBlur],
                             [imgCanny, imgContour, imgBlank]))

cv2.imshow('Stack', imgStack)
cv2.waitKey(0)


该回答引用于gpt与OKX安生共同编写:
  • 该回答引用于gpt与OKX安生共同编写:

针对农田分类和面积计算问题,可以借助OpenCV库和Python语言实现。可以使用以下步骤进行处理:

  1. 读取图像并将其转换为灰度图像。
import cv2

img = cv2.imread('field.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  1. 对灰度图像进行二值化处理,以便提取农田区域。
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
  1. 对二值化后的图像进行形态学操作,以填充空洞和平滑边缘。
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
opened = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
  1. 使用轮廓检测方法提取农田区域的轮廓。
contours, hierarchy = cv2.findContours(opened, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  1. 对轮廓进行筛选,保留面积大于某一特定阈值的轮廓,即认为这些轮廓所代表的是农田区域。
min_area = 1000
fields = []
for contour in contours:
    area = cv2.contourArea(contour)
    if area > min_area:
        fields.append(contour)
  1. 对筛选出的轮廓进行绘制,并计算农田区域的面积。
result = img.copy()
for field in fields:
    cv2.drawContours(result, [field], -1, (0, 0, 255), 2)

print('农田数量:', len(fields))
for i, field in enumerate(fields):
    area = cv2.contourArea(field)
    print('农田{}面积为: {}平方像素'.format(i+1, area))
  • 以下是完整的示例程序,包括纹理特征提取、分类和面积计算:
import cv2
import numpy as np
from sklearn.ensemble import RandomForestClassifier

# 定义GLCM算法相关参数
distance = 1
angle = 0
levels = 256
symmetric = True
normed = True

# 计算农田区域的纹理特征
def calculate_texture_features(img):
    # 计算图像的GLCM矩阵
    glcm = cv2.calcGLCM(img, [distance], [angle], levels, symmetric, normed)

    # 提取GLCM统计数据
    contrast = cv2.compareHist(glcm[:, :, 0], np.array([1]), method=cv2.HISTCMP_CHISQR_ALT)
    dissimilarity = cv2.compareHist(glcm[:, :, 1], np.array([1]), method=cv2.HISTCMP_CHISQR_ALT)
    homogeneity = cv2.compareHist(glcm[:, :, 2], np.array([1]), method=cv2.HISTCMP_CHISQR_ALT)
    energy = cv2.compareHist(glcm[:, :, 3], np.array([1]), method=cv2.HISTCMP_CHISQR_ALT)
    correlation = cv2.compareHist(glcm[:, :, 4], np.array([1]), method=cv2.HISTCMP_CHISQR_ALT)

    # 返回纹理特征向量
    return np.array([contrast, dissimilarity, homogeneity, energy, correlation])

# 加载农田图像和类别标签
X = []
y = []
for i in range(1, 101):
    img = cv2.imread(f"farm_{i}.png")
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    X.append(calculate_texture_features(gray))
    if i <= 50:
        y.append(0)  # Wheat类别
    else:
        y.append(1)  # Corn类别

# 训练随机森林分类器
clf = RandomForestClassifier(n_estimators=100)
clf.fit(X, y)

# 加载新的农田图像,进行分类和面积计算
img = cv2.imread("new_farm.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 对农田图像进行分割,获取每个农田区域
fields = get_fields(gray)

# 遍历每个农田区域,计算其面积和类别
total_area = 0
wheat_area = 0
corn_area = 0
for field in fields:
    # 计算农田区域的纹理特征
    features = calculate_texture_features(field)

    # 对农田区域进行分类
    prediction = clf.predict([features])[0]
    if prediction == 0:
        wheat_area += area(field)
    else:
        corn_area += area(field)

    # 更新总面积
    total_area += area(field)

# 输出结果
print(f"Total area: {total_area} square meters")
print(f"Wheat area: {wheat_area} square meters")
print(f"Corn area: {corn_area} square meters")

该回答参考ChatGPT:
使用OpenCV对农田进行分类和面积计算可以分为以下几个步骤:
收集和准备数据。收集拍摄的农田图像,并对图像进行预处理,如裁剪、去噪、灰度化、二值化等操作。
提取纹理特征。使用OpenCV的纹理分析函数,如LBP、GLCM等,提取图像的纹理特征。这些纹理特征可以用于分类和面积计算。
分类器训练。将提取的纹理特征作为分类器的输入,训练一个分类器,如支持向量机(SVM)、k-近邻(k-NN)等。训练好的分类器可以用于对新的农田图像进行分类。
分类和面积计算。使用训练好的分类器对新的农田图像进行分类,并将分类结果与图像面积相乘,即可得到该类农田的总面积。重复这个过程,即可对不同类别的农田进行分类和面积计算。
下面是一个使用OpenCV进行纹理分类和面积计算的示例代码:

import cv2
import numpy as np

# 读取图像
img = cv2.imread('field.jpg')

# 预处理图像
img = img[100:400, 100:400]   # 裁剪
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)   # 灰度化
gray = cv2.medianBlur(gray, 5)   # 中值滤波
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)   # 二值化

# 提取纹理特征
radius = 1
n_points = 8 * radius
lbp = cv2.xfeatures2d.SIFT_create()
kp = lbp.detect(gray, None)
kp, des = lbp.compute(gray, kp)

# 训练分类器
trainData = np.float32(des)
responses = np.array([0, 1])   # 假设有两种不同的农田类型
svm = cv2.ml.SVM_create()
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_LINEAR)
svm.setTermCriteria((cv2.TERM_CRITERIA_MAX_ITER, 100, 1e-6))
svm.train(trainData, cv2.ml.ROW_SAMPLE, responses)

# 分类和面积计算
img_area = img.shape[0] * img.shape[1]
classes = ['Type1', 'Type2']
for i, classname in enumerate(classes):
    mask = np.zeros_like(gray)
    mask[thresh == 255] = 1
    mask[svm.predict(des) != i] = 0
    class_area = np.sum(mask) / img_area
    print('{}: {:.2f}'.format(classname, class_area))

基于最新版ChatGPT4的回答,望采纳!!!有其他问题也可以询问我哦💕(最新版更智能,功能更加强大):
进行农田分类和面积计算,可以使用 OpenCV 进行图像处理和特征提取。下面是一个简单的流程:

加载图像并进行预处理:首先使用 OpenCV 的 imread() 函数加载图像,并对其进行必要的预处理操作,例如去噪、平滑、灰度化等。

特征提取:通过纹理特征提取技术,如局部二值模式(LBP)、灰度共生矩阵(GLCM)或Gabor滤波器等方法,从图像中提取纹理特征,将每个像素点的纹理信息转换为特定的特征向量,作为输入样本的特征表示。

训练分类器:使用机器学习算法,如支持向量机(SVM)或随机森林(Random Forest),对样本进行训练,构建分类器模型。

分类:使用分类器对新的农田图像进行分类,将其分为不同的农田类型。

面积计算:根据分类结果,使用 OpenCV 的轮廓检测功能计算出各个农田区域的边界,并计算每个农田区域的面积。

下面是一个简单的代码示例,仅供参考:


python
import cv2

# 读取图像
img = cv2.imread('farm.png')

# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# LBP特征提取
lbp = cv2.xfeatures2d.SIFT_create()
keypoints, descriptors = lbp.detectAndCompute(gray, None)

# 构建SVM分类器模型并训练
svm = cv2.ml.SVM_create()
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_LINEAR)
svm.trainAuto(descriptors, cv2.ml.ROW_SAMPLE, labels)

# 对新图像进行分类
test_img = cv2.imread('test_farm.png')
test_gray = cv2.cvtColor(test_img, cv2.COLOR_BGR2GRAY)
test_keypoints, test_descriptors = lbp.detectAndCompute(test_gray, None)
result = svm.predict(test_descriptors)

# 计算面积
contours, hierarchy = cv2.findContours(result, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
    area = cv2.contourArea(contour)
    print("农田面积为:", area)

需要注意的是,这只是一个简单的示例代码,实际应用中还需要根据具体情况进行调整和优化。同时,纹理特征提取方法、机器学习算法和分类器参数等也会对分类结果和面积计算产生影响,需要根据实际情况进行选择和调整。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
实现农田分类和面积计算,可以分为以下步骤:

  1. 图像预处理:将农田图像进行预处理,包括灰度化、滤波、边缘检测等。

  2. 特征提取:从预处理后的图像中提取特征,比如纹理特征、形状特征等。

  3. 分类器训练:利用已标注的农田图像和其对应的类别信息,训练分类器模型,比如支持向量机(SVM)、决策树(Decision Tree)等。分类器模型将根据输入的图像特征,判断该图像属于哪一类别。

  4. 分类结果输出:对新的农田图像进行分类,输出分类结果。

  5. 面积计算:依据分类后的结果,利用数学公式计算各类别农田面积。

下面是一份伪代码:

import cv2
import numpy as np

# 1.图像预处理
img = cv2.imread("field_image.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)

# 2.提取纹理特征
lbp = cv2.xfeatures2d.SIFT_create()

# 计算LBP特征
keypoints, descriptors = lbp.detectAndCompute(blurred, None)

# 3.分类器训练
# 建立分类器模型
svm = cv2.ml.SVM_create()

# 准备训练数据
X_train = descriptors
y_train = np.array([0, 0, 1, 1])  # 假设有4张图像,前面两张属于类别0,后面两张属于类别1

# 训练分类器
svm.trainAuto(X_train, cv2.ml.ROW_SAMPLE, y_train)

# 4.分类结果输出
# 对新的农田图像进行分类
keypoints2, descriptors2 = lbp.detectAndCompute(new_image, None)
result = svm.predict(descriptors2)

# 5.面积计算
# 假设分类0表示农田,1表示非农田
field_mask = result == 0  # 获取农田区域的掩码
field_area = np.count_nonzero(field_mask)  # 计算农田面积,单位为像素

以上代码仅供参考,具体实现中需要根据实际情况进行调整。
如果我的回答解决了您的问题,请采纳!

针对这个问题,可以采用以下步骤进行农田分类和面积计算:
1. 数据预处理:首先需要准备一些农田的图像数据,可以从现场拍摄或者网络上下载。对于每张图像,需要进行预处理,包括图像去噪、灰度化、二值化等操作,以便后续的特征提取和分类。
2. 特征提取:在进行农田分类时,可以采用纹理特征进行分类。常用的纹理特征包括灰度共生矩阵(GLCM)、局部二值模式(LBP)等。这些特征可以通过opencv库中的函数进行提取。
3. 分类器训练:在提取完特征后,需要使用机器学习算法进行分类器训练。常用的分类算法包括支持向量机(SVM)、随机森林(Random Forest)等。可以使用sklearn库中的函数进行分类器训练。
4. 分类器测试:训练好分类器后,需要对测试集进行测试,以评估分类器的性能。可以使用sklearn库中的函数进行测试,并计算分类器的准确率、召回率等指标。
5. 面积计算:在完成农田分类后,可以根据分类结果计算每种农田的面积。可以使用opencv库中的函数进行轮廓提取,并计算轮廓的面积。
总之,通过以上步骤,可以使用opencv进行农田分类和面积计算。需要注意的是,不同的农田可能具有不同的纹理特征,因此需要根据实际情况选择合适的特征和分类算法。同时,需要对数据进行充分的预处理和测试,以保证分类器的准确性和稳定性。不知道你这个问题是否已经解决, 如果还没有解决的话:


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^