使用 opencv 在种植园航拍图像中分割树木的最佳方法
best way to segment a tree in plantation aerial image using opencv
所以我想从航拍图像中分割出一棵树
样本图片(原始图片):
我期待这样的结果(或更好):
我做的第一件事是在 opencv 中使用阈值函数,但没有得到预期的结果(它无法分割树冠),然后我在 photoshop 中使用一些调整后的参数使用黑白滤镜(结果如下所示w)并进行阈值和形态学过滤并得到如上所示的结果。
我的问题,是否有一些方法可以在不首先使用 photoshop 的情况下对图像进行分割,并生成像第二张图像(或更好)的分割图像?或者有没有办法像第三张图片一样制作图片?
ps:您可以在此处阅读 photoshop 黑白滤镜问题:https://dsp.stackexchange.com/questions/688/whats-the-algorithm-behind-photoshops-black-and-white-adjustment-layer
您可以在 OpenCV 中完成。下面的代码将基本上执行您在 Photoshop 中执行的相同操作。您可能需要调整一些参数才能完全您想要的。
#include "opencv2\opencv.hpp"
using namespace cv;
int main(int, char**)
{
Mat3b img = imread("path_to_image");
// Use HSV color to threshold the image
Mat3b hsv;
cvtColor(img, hsv, COLOR_BGR2HSV);
// Apply a treshold
// HSV values in OpenCV are not in [0,100], but:
// H in [0,180]
// S,V in [0,255]
Mat1b res;
inRange(hsv, Scalar(100, 80, 100), Scalar(120, 255, 255), res);
// Negate the image
res = ~res;
// Apply morphology
Mat element = getStructuringElement( MORPH_ELLIPSE, Size(5,5));
morphologyEx(res, res, MORPH_ERODE, element, Point(-1,-1), 2);
morphologyEx(res, res, MORPH_OPEN, element);
// Blending
Mat3b green(res.size(), Vec3b(0,0,0));
for(int r=0; r<res.rows; ++r) {
for(int c=0; c<res.cols; ++c) {
if(res(r,c)) { green(r,c)[1] = uchar(255); }
}
}
Mat3b blend;
addWeighted(img, 0.7, green, 0.3, 0.0, blend);
imshow("result", res);
imshow("blend", blend);
waitKey();
return 0;
}
生成的图像是:
混合图像为:
这在过去一直是一个有趣的研究课题——主要是在遥感文献中。
虽然建议使用 OpenCV 的形态学方法在某些情况下会起作用,但您可能需要考虑更复杂的方法(取决于您的数据的可变性以及您想要构建的检测器的鲁棒性)。
例如,this paper, and those who cite it - 让您了解已尝试的内容。
务实地说 - 我认为一个巧妙的解决方案是更多地建立在统计纹理分析的基础上。有很多方法可以将图像的区域分类(然后计数)为属于纹理(共现矩阵、滤波器组、文本子、小波等)。
遗憾的是,这是 OpenCV 相当不足的领域 - 它只提供了有用算法的一个子集......但是,这里有一些快速的想法(none 我已经尝试过直接地,我所知道的是基于底层的 OpenCV):
- 使用 OpenCV Gabor 过滤器支持和聚类 (for example)。
- 您还可以使用 Local Binary Patterns.
训练 OpenCV SVM
- 一个新库 - 但可能与静态图像不太相关 - LIBDT
无论如何,我希望你能找到适合你目的的东西!
所以我想从航拍图像中分割出一棵树
样本图片(原始图片):
我期待这样的结果(或更好):
我做的第一件事是在 opencv 中使用阈值函数,但没有得到预期的结果(它无法分割树冠),然后我在 photoshop 中使用一些调整后的参数使用黑白滤镜(结果如下所示w)并进行阈值和形态学过滤并得到如上所示的结果。
我的问题,是否有一些方法可以在不首先使用 photoshop 的情况下对图像进行分割,并生成像第二张图像(或更好)的分割图像?或者有没有办法像第三张图片一样制作图片?
ps:您可以在此处阅读 photoshop 黑白滤镜问题:https://dsp.stackexchange.com/questions/688/whats-the-algorithm-behind-photoshops-black-and-white-adjustment-layer
您可以在 OpenCV 中完成。下面的代码将基本上执行您在 Photoshop 中执行的相同操作。您可能需要调整一些参数才能完全您想要的。
#include "opencv2\opencv.hpp"
using namespace cv;
int main(int, char**)
{
Mat3b img = imread("path_to_image");
// Use HSV color to threshold the image
Mat3b hsv;
cvtColor(img, hsv, COLOR_BGR2HSV);
// Apply a treshold
// HSV values in OpenCV are not in [0,100], but:
// H in [0,180]
// S,V in [0,255]
Mat1b res;
inRange(hsv, Scalar(100, 80, 100), Scalar(120, 255, 255), res);
// Negate the image
res = ~res;
// Apply morphology
Mat element = getStructuringElement( MORPH_ELLIPSE, Size(5,5));
morphologyEx(res, res, MORPH_ERODE, element, Point(-1,-1), 2);
morphologyEx(res, res, MORPH_OPEN, element);
// Blending
Mat3b green(res.size(), Vec3b(0,0,0));
for(int r=0; r<res.rows; ++r) {
for(int c=0; c<res.cols; ++c) {
if(res(r,c)) { green(r,c)[1] = uchar(255); }
}
}
Mat3b blend;
addWeighted(img, 0.7, green, 0.3, 0.0, blend);
imshow("result", res);
imshow("blend", blend);
waitKey();
return 0;
}
生成的图像是:
混合图像为:
这在过去一直是一个有趣的研究课题——主要是在遥感文献中。
虽然建议使用 OpenCV 的形态学方法在某些情况下会起作用,但您可能需要考虑更复杂的方法(取决于您的数据的可变性以及您想要构建的检测器的鲁棒性)。
例如,this paper, and those who cite it - 让您了解已尝试的内容。
务实地说 - 我认为一个巧妙的解决方案是更多地建立在统计纹理分析的基础上。有很多方法可以将图像的区域分类(然后计数)为属于纹理(共现矩阵、滤波器组、文本子、小波等)。
遗憾的是,这是 OpenCV 相当不足的领域 - 它只提供了有用算法的一个子集......但是,这里有一些快速的想法(none 我已经尝试过直接地,我所知道的是基于底层的 OpenCV):
- 使用 OpenCV Gabor 过滤器支持和聚类 (for example)。
- 您还可以使用 Local Binary Patterns. 训练 OpenCV SVM
- 一个新库 - 但可能与静态图像不太相关 - LIBDT
无论如何,我希望你能找到适合你目的的东西!