lunedì 31 marzo 2014

Visione Artificiale - Lab 3: misure su elementi dell'immagine

MAIN
#include <opencv2\opencv.hpp>
#include "MeasurableObject.h"


using namespace std;
using namespace cv;


int main() {

// Load a RGB image called "input"
Mat3b input = imread("../images/Immagini/TESI33.bmp");
imshow("Originale", input);

// Clone input to an image called "output"
Mat3b output = input.clone();

// Convert input to a grayscale called "img"
Mat1b img;
cvtColor(input, img, CV_RGB2GRAY);
imshow("Scala di grigi", img);

// Get binary image. Background = 0, Foreground > 0
threshold(img, img, 90, 255, THRESH_BINARY_INV);
imshow("Sogliata", img);

// Find Connected Component 
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
vector<MeasurableObject> objects;

findContours(img.clone(), contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE);

int idx = 0;
for( ; idx >= 0; idx = hierarchy[idx][0] ){
Mat1b mask(img.rows, img.cols, uchar(0));
//Scalar color( rand()&255, rand()&255, rand()&255 );
drawContours(mask, contours, idx, Scalar(255), CV_FILLED, 8, hierarchy);

//Creo un oggetto di tipo misurabile a cui aggiungo la mask appena trovata
MeasurableObject obj;
obj.addMask(mask);
//Associo anche il suo contorno
obj.AddContour(contours[idx]);

//Inserisco l'oggetto in un vettore di oggetti misurabili (le mask)
objects.push_back(obj);

}

//Per ogni oggetto misurabile presente nel vettore (appena riempito)
for(int i=0;i<objects.size();++i){
float area;
MeasurableObject& obj = objects[i];

//Calcolo l'area
String name_mask = "Mask "; char digit = (char)(((int)'0')+i);;
name_mask.push_back(digit); cout << name_mask << endl;
imshow(name_mask, obj._mask);
area = obj.area();
cout << "Area: " << area << endl;

//Calcolo il baricentro e lo disegno
Point2f baricenter = obj.baricenter();
circle(output, baricenter, 3, Scalar(0, 255, 0));

//Calcolo il Bounding Box
Rect bbox = obj.BoundingBox();
rectangle(output, bbox, Scalar(255, 0, 0));

//Calcolo la rettangolarità
float R;
R = obj.Rectangularity(bbox);
cout << "Rectangularity: " << R << endl;

//Calcolo il perimetro
float P;
P = obj.Perimeter();
cout << "Perimeter: " << P << endl;

//Calcolo la circolarità - I metodo
float C1;
C1 = obj.Circularity1();
cout << "Circularity (I): "<< C1 << endl;

//Calcolo la circolarità - II metodo
float C2;
C2 = obj.Circularity2();
cout << "Circularity (II): "<< C2 << endl;

//Calcolo il Box Oriented
RotatedRect orientedBBox = obj.OrientedBoundingBox();
//Lo disegno sull'immagine
Point2f pts[4];
orientedBBox.points(pts);
for(int j=0; j<4; ++j) {
line(output, pts[j], pts[(j+1)%4], Scalar(0,255,255));
}

cout << endl;
}

imshow("output", output);
waitKey();

return 0;
}

MEASURABLEOBJECT.CPP
#include "MeasurableObject.h"

void MeasurableObject::WriteOnImageAt(Mat3b img, const Point& where, const Scalar& color) 
{
int fontFace = FONT_HERSHEY_PLAIN;
double fontScale = 1.0;
int thickness = 1;

int h = 0;
for(unsigned i=0; i<_text.size(); ++i) {
int baseline = 0;
h += getTextSize(_text[i], fontFace, fontScale, thickness, &baseline).height + 5;
putText(img, _text[i], Point(where.x, where.y + h), fontFace, fontScale, color, thickness);
}
}

void MeasurableObject::addMask(const Mat1b& mask){
_mask = mask.clone();
}

void MeasurableObject::AddContour(const vector<Point>& contour){
_contour = contour;
}

float MeasurableObject::area(){
float area = 0.f;
for(int r=0;r<_mask.rows;++r){
for(int c=0;c<_mask.cols;++c){
if(_mask(r,c)){
++area;
}
}
}
return area;
}

Point2f MeasurableObject::baricenter(){
float sumx = 0.f;
float sumy = 0.f;
Point2f baricenter;
float a = area();

for(int r=0;r<_mask.rows;++r)
for(int c=0;c<_mask.cols;++c){
if(_mask(r,c)){
sumx += r;
sumy += c;
}
}
baricenter.x = sumx / a;
baricenter.y = sumy / a;

return baricenter;

}

Rect MeasurableObject::BoundingBox(){
int x_min = INT_MAX;
int y_min = INT_MAX;
int x_max = 0;
int y_max = 0;

for(int r=0;r<_mask.rows;++r){
for(int c=0;c<_mask.cols;++c){
if(_mask(r,c)){
if(c>x_max)
x_max = c;
if(r>y_max)
y_max = r;
if(c<x_min)
x_min = c;
if(r<y_min)
y_min = r;
}
}
}
Rect bbox(Point(x_min, y_min), Point(x_max+1, y_max+1));
return bbox;
}

float MeasurableObject::Rectangularity(Rect bbox){
float a = area();
float ae = bbox.height*bbox.width;
float R = a/ae;

return R;
}

bool MeasurableObject::AreConnected4(const Point& p, const Point& q) const {
//Connessione4: distanza City Block deve essere pari a 1 -> |i-h| + |j-k| = 1
return (abs(p.x - q.x) + abs(p.y - q.y) == 1);
}

bool MeasurableObject::AreConnected8(const Point& p, const Point& q) const {
//Connessione8: distanza Chessboard -> max {|i-h| + |j-k|} = 1
return (abs(p.x - q.x) <= 1) && (abs(p.y - q.y) <= 1);
}

float MeasurableObject::Perimeter(){
unsigned N = _contour.size();
float n4 = 0.f;
float n8 = 0.f;

for(int i=0;i<N;++i){
const Point& p = _contour[i];
const Point& q = _contour[(i+1)%N];
if(AreConnected4(p,q)) 
n4++;
else
if(AreConnected8(p,q))
n8++;
}
return (n4 + sqrt(2.f)*n8);
}

float MeasurableObject::Circularity1(){
float perimeter = Perimeter();
return ((4*CV_PI)*area()/pow(perimeter,2));
}

float MeasurableObject::Circularity2(){
float mi = 0.f;
float sigma = 0.f;
unsigned K = _contour.size();
Point2f bar = baricenter();

for(int i=0;i<K;++i){
const Point p = _contour[i];
mi += sqrt(pow(p.x-bar.x,2)+pow(p.y-bar.y,2));
}
mi = mi/(float)K;
for(int i=0;i<K;++i){
const Point p = _contour[i];
sigma += pow(sqrt(pow(p.x-bar.x,2)+pow(p.y-bar.y,2))-mi,2);
}
sigma = sigma/K;

return(mi/sigma);
}

RotatedRect MeasurableObject::OrientedBoundingBox() const {
return minAreaRect(_contour);
}







Nessun commento:

Posta un commento