How can I avoid detecting the frame of an image when using findContours
(OpenCV)? Until I found OpenCV findContours allways finds two contours for every object and implemented that answer, I was not detecting the internal object consistently (object line was broken into several pieces), but now I detect the image frame every time.
The image is of a quad-rotor UAV seen from the bottom; I am using a series of pictures for 'training' object detection. For that, I need to be sure that I can consistently get the UAV object. I guess I could invert the colors, but that seems like a dirty hack.
The images are first the input image just before findContours
, and the resulting contours. I have seven test images, and all seven has a frame and the UAV. The hu moments are very similar (as expected).
The code (C++11, and quite messy) for finding the contours/objects and calculating the hu moments:
#include <opencv/cv.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <fstream>
#include <string>
using namespace cv;
using namespace std;
#define EROSION_SIZE 1
#define ERODE_CANNY_PREP_ITERATIONS 5
int main() {
Mat image, canny_output, element, padded;
RNG rng(12345);
int numbers[] = {195, 223, 260, 295, 331, 368, 396};
string pre = "/home/alrekr/Pictures/UAS/hu-images/frame_";
string middle = "_threshold";
string post = ".png";
string filename = "";
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
ofstream fout("/home/alrekr/Pictures/UAS/hu-data/hu.dat");
element = getStructuringElement(MORPH_RECT,
Size(2*EROSION_SIZE + 1, 2*EROSION_SIZE+1),
Point(EROSION_SIZE, EROSION_SIZE));
namedWindow("Window", CV_WINDOW_AUTOSIZE);
for (int i : numbers) {
filename = pre + to_string(i) + middle + post;
image = imread(filename, CV_LOAD_IMAGE_GRAYSCALE);
erode(image, image, element, Point(-1,-1), ERODE_CANNY_PREP_ITERATIONS);
imwrite("/home/alrekr/Pictures/UAS/hu-data/prep_for_canny_" + to_string(i) + ".png", image);
findContours(image, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
vector<Moments> mu(contours.size());
if(contours.size() < 1) {
cout << "No contours found" << endl;
} else {
cout << "Contours found: " << contours.size() << endl;
}
vector<Point2f> mc(contours.size());
for(int j = 0; j < (int)contours.size(); j++) {
mc[j] = Point2f(mu[j].m10/mu[j].m00 , mu[j].m01/mu[j].m00);
}
Mat drawing = Mat::zeros(image.size(), CV_8UC3);
for(int j = 0; j < (int)contours.size(); j++) {
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255));
drawContours(drawing, contours, j, color, 2, 8, hierarchy, 0, Point());
imshow("Window", drawing);
waitKey(0);
}
imwrite("/home/alrekr/Pictures/UAS/hu-data/cannied_" + to_string(i) + ".png", drawing);
fout << "Frame " << i << "\n";
for(int j = 0; j < (int)contours.size(); j++) {
mu[j] = moments(contours[j]);
double hu[7];
HuMoments(mu[j], hu);
fout << "Object " << to_string(j) << "\n";
fout << hu[0] << "\n";
fout << hu[1] << "\n";
fout << hu[2] << "\n";
fout << hu[3] << "\n";
fout << hu[4] << "\n";
fout << hu[5] << "\n";
fout << hu[6] << "\n";
}
}
fout.close();
return 0;
}
Aucun commentaire:
Enregistrer un commentaire