Hi, to all
I want to develop a program to count plants in a crop, I have used some methods for segment the plants of the ground in OpenCV like inRange of HSV, Green Channel Segmentation and Histogram Backprojection but I have still some issues to get the total shape of the plants.
I tested my algorithm with the following images in some lighting conditions
For the HSV Segmentation I use four regions to get the Max and Min Values for each mask, so I sum the four masks of each segmentation to obtain an total mask, for the Green Channel Segmentation I split the channels of the BGR image and I apply the following equation to get the final mask T = 2*G - R - G, I also experimented normalizing the Green Channel to get better results in more light conditions and I apply the same equation, also I backproject the HS Histogram with a Sample of Color of a Plant and a Mask of that Plant(included in the images of the link at the bottom), so I get the following results
(In this case the HSV segmentation was the best, but in the next images Normalized Green Channel have better results)
My question is, is there any another method to rightly segment the plants? or how can I improve my code? I will appreciate every response, Link to Images
#include <iostream>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/videoio.hpp>
using namespace std;
using namespace cv;
String rutavideo;
Mat imagen;
int opcion = 0;
char c;
vector<Mat> canalesnorm(3);
vector<Mat> canales(3);
//Matrices para HSV
Mat procesado, procesadohsv;
//Matrices Procesamiento HSV
Mat verdenorm, azulnorm,rojonorm, normalizada, b1, b2, b3, b4;
//Matrices Procesado Capa Verde
Mat verdenormal;
//Matrices para Backprojection
Mat roi, mascararoi, roihsv;
//Procesado Capa Verde Normalizado
Mat verdenormalizado;
//Mascaras salida Colores
Mat mascarahsv, mascaranormal, mascaranormalizada, mascarabackprojection;
Mat ecualizado;
int h_bins = 26; int s_bins = 200;
int bins = 7;
int main(int argc, char *argv[])
{
cout << "Parameters:" << endl;
cout << "1.- Original Image" << endl;
cout << "2.- Image of color of the plant" << endl;
cout << "3.- Mask of 2" << endl;
if(argc < 4)
{
cout << argv[0] << endl;
cout << argv[1] << endl;
cout << argv[2] << endl;
cout << argv[3] << endl;
cout << "Error, ingrese un numero valido de parametros" << endl;
return -1;
}
imagen = imread(argv[1],IMREAD_COLOR);
if(imagen.empty()){
cout << "No hay imagen para segmentar, escriba una ruta valida" << endl;
return -1;
}
//Codigo backprojection
roi = imread(argv[2],IMREAD_COLOR);
if(roi.empty()){
cout << "No hay imagen patron de verde, escriba una ruta valida" << endl;
return -1;
}
mascararoi = imread(argv[3],IMREAD_GRAYSCALE);
if(mascararoi.empty()){
cout << "No hay imagen de la mascara, escriba una ruta valida" << endl;
return -1;
}
MatND histograma;
MatND Backprojection;
const int channels[] = {0, 1}; //Canal Hue y Canal Saturation
if(bins < 1) bins = 1;
int histSize[] = { h_bins, s_bins };
const float rangohue[] = {0, 179};
const float rangosaturation[] = {0, 255};
const float* ranges[] = {rangohue, rangosaturation};
cvtColor(roi,roihsv,COLOR_BGR2HSV);
//Codigo Segmentacion HSV
medianBlur(imagen, procesado, 5);
cvtColor(procesado,procesado,COLOR_BGR2HSV);
inRange(procesado,Scalar(30,15,150),Scalar(60,255,255),b1);
inRange(procesado,Scalar(55,11,74),Scalar(75,255,255),b2);
inRange(procesado,Scalar(63,6,73),Scalar(83, 255, 255),b3);
inRange(procesado,Scalar(29, 40, 77),Scalar(49, 255, 255),b4);
procesadohsv = b1 + b2+ b3 + b4;
medianBlur(procesadohsv,procesadohsv,3);
//Codigo Segmentacion por Canal Verde
split(imagen,canales);
verdenormal = 2*canales[1] - canales[0] - canales[2];
medianBlur(verdenormal,verdenormal,3);
//Codigo Segmentacion Canal Verde Normlizado
normalize(canales[1],canales[1],0, 255, NORM_MINMAX, -1, Mat());
verdenormalizado = 2*canales[1] - canales[0] - canales[2];
merge(canales,ecualizado);
medianBlur(verdenormalizado,verdenormalizado,3);
threshold(verdenormalizado,verdenormalizado,27,255,THRESH_BINARY);
//Codigo de Backprojection
calcHist(&roihsv,1,channels,mascararoi,histograma,2,histSize,ranges,true,false);
normalize( histograma, histograma, 0, 255, NORM_MINMAX, -1, Mat() );
calcBackProject(&procesado, 1, channels, histograma, Backprojection, ranges,true);
filter2D(Backprojection,Backprojection,-1,getStructuringElement(MORPH_ELLIPSE,Size(5,5)));
medianBlur(Backprojection,Backprojection,3);
//Mascaras
imagen.copyTo(mascarabackprojection,Backprojection);
imagen.copyTo(mascaranormal,verdenormal);
imagen.copyTo(mascaranormalizada,verdenormalizado);
imagen.copyTo(mascarahsv,procesadohsv);
imshow("Mascara Original Verde", mascaranormal );
imshow("Mascara Normalizada", mascaranormalizada);
imshow("Mascara HSV", mascarahsv);
imshow("Mascara Backprojection",mascarabackprojection);
imshow("Ecualizado",ecualizado);
imshow("Imagen Original",imagen);
waitKey(0);
return 0;
}