equalizeHistimgin, imgout; Câu 2: Lọc trong không gian.. Ứng dụng lọc làm trơn trong không gian bằng mặt nạ trung bình và mặt nạ Gauss a.. Cơ bản về lọc trong không gian Ảnh tồn tại tr
Trang 1ÔN TẬP CHUYÊN ĐỀ 1
Câu 1: Mục đích của việc cân bằng historam? Xây dựng và cài đặt thuật toán cân bằng histogram tự động.
a Mục đích
Mục đích của cân bằng histogram là làm cho histogram trở nên đồng đều Khi đó ta làm tăng được độ tương phản của ảnh (làm cho ảnh trở nên rõ hơn)
b Xây dựng công thức
Cân bằng histogram được cho bằng phương trình: s=T(r)=(L-1)
r pr w dw
0 ) ( với pr : Là hàm mật độ xác suất pr(w): Xác suất xảy ra mức xám w
Trong xác suất, tích phân của hàm mật độ là hàm phân phối Công thức trên có w là biến
liên tục, ta không thể lập trình nó Ta phải dùng công thức rời rạc: sk=T(rk)=(L-1)
k j
j
r r p
0 ) ( với k= 0,1,2,…,L-1
c Cài đặt thuật toán
void HistogramEqualization(Matimgin, Matimgout) //Can bang Histogram
{
int M = imgin.size().height;
int N = imgin.size().width;
int x, y;
int r, h[L];
for (r = 0; r < L; r++)
h[r] = 0;
for (x = 0; x < M; x++)
for (y = 0; y < N; y++)
{
r = imgin.at<uchar>(x, y);
h[r]++;
}
double p[L];
for (r = 0; r < L; r++)
p[r] = (double)h[r] / (M*N);
double s[L];
int j, k;
for (k = 0; k < L; k++)
{
s[k] = 0;
for (j = 0; j <= k; j++)
s[k] += p[j];
s[k] *= L - 1;
}
for (x = 0; x < M; x++)
for (y = 0; y < N; y++)
{
r = imgin.at<uchar>(x, y);
Trang 2imgout.at<uchar>(x, y) = (uchar)s[r];
}
return;
}
d Hàm trong openCV.
equalizeHist(imgin, imgout);
Câu 2: Lọc trong không gian Ứng dụng lọc làm trơn trong không gian bằng mặt nạ trung bình và mặt nạ Gauss
a Cơ bản về lọc trong không gian
Ảnh tồn tại trong miền không gian, nếu xử lý trong miền không gian thì không được tốt, ta chuyển ảnh sang miền tần số để xử lý, xử lý xong chuyển lại sang miền không gian.
Người ta dùng một cửa sổ nhỏ để lọc trong không gian, cửa sổ nhỏ thường được gọi là mặt
nạ (mask), tên thông dụng nhất là mặt nạ, opencv thường gọi là Kernels.
b Xây dựng công thức
Giá trị của bộ lọc người ta sẽ cho tùy vào yêu cầu cụ thể
Bộ lọc trong không gian được cho bằng phương trình sau: (Sum Convolution)
g (x , y )=w (−1,−1 ) f ( x−1, y−1)+w (−1,0 ) f ( x−1, y )+…+w (0,0) f ( x , y )+…+w (1,1) f (x +1, y+1)
Kích thước bộ lọc thường là số lẻ để có phần tử trung tâm (3x3 hoặc 5x5)
Tổng quát lọc trong không gian được cho bằng phương trình :
g(x,y)=
aa
b b t
t y s x f t s
w( , ) ( , )
Trong đó :
mxn là kích thước của bộ lọc
a=m/2 và b=n/2
w(s,t) là mặt nạ lọc hay bộ lọc
f(x,y) là điểm ảnh đầu vào
g(x,y) là điểm ảnh đầu ra
Phép toán lọc trong không gian được gọi là tổng chập (convolution).
Đối với lọc tuyến tính, mặt nạ lọc thường dùng là mặt nạ trung bình hay mặt nạ Gauss Mặt nạ càng lớn, ảnh càng bị nhòe.
Trang 3Ví dụ: mặt nạ lọc trung bình và mặt nạ Gauss:
c Cài đặt thuật toán
void MyFilter2D(Matimgin, Mat imgout, Matw)
{
int m = w.size().height;
int n = w.size().width;
int M = imgin.size().height;
int N = imgin.size().width;
int x, y, s, t;
int a = m / 2, b = m / 2;
float r;
for (x = a; x < M - a; x++)
for (y = b; y < N - b; y++)
{
r = 0;
for (s = -a; s <= a; s++) for (t = -b; t <= b; t++)
r += w.at<float>(s + a, t + b) *imgin.at<uchar>(x + s, y + t);
imgout.at<uchar>(x, y) = (uchar)r;
}
return;
} //Có sẵn hàm filter2D trong VS
void SmoothingLinearFilter(Matimgin, Matimgout)
{
int m = 15, n = 15;
Mat w = Mat(m, n, CV_32FC1);
int x, y;
for (x = 0; x < m; x++)
for (y = 0; y < n; y++)
w.at<float>(x, y) = 1.0 / (m*n);
//MyFilter2D(imgin, imgout, w);
filter2D(imgin, imgout, CV_8UC1, w);
return;
}
d Hàm trong openCV
blur(imgin, imgout, Size (35, 35));
GaussianBlur(imgin, imgout, Size (0,0),5);
Câu 3: Các bước lọc ảnh trong miền tần số (7 bước) Xóa nhiễu Morie
a Các bước lọc ảnh trong miền tần số:
- Bước 1: Cho ảnh đầu vào f(x,y) có kích thước MxN Mở rộng ảnh có kích thước là PxQ
Cụ thể P=2M, Q=2N.
- Bước 2: Thêm zero (số 0) vào phần mở rộng, ta được ảnh fp(x,y).
16 1
x
x
9
Trang 4- Bước 3: Nhân fp(x,y) với (-1)x+y để dời F(0,0) vào tâm ảnh Do ảnh là số thực nên phổ luôn luôn đối xứng.
- Bước 4: Biến đổi Fourier của ảnh ở Bước 3 ta được F(u,v).
- Bước 5: Tạo hàm lọc đối xứng, có giá trị thực H(u,v), có kích thước là PxQ, có tâm là (P/2,Q/2) Thực hiện phép nhân G(u,v) = F(u,v)*H(u,v).
- Bước 6: Thu được ảnh đã xử lý bằng biến đổi Fourier ngược, lấy phần thực và dời trở lại gốc tọa độ
- Bước 7: Bỏ phần đã mở rộng, ta thu được ảnh g(x,y) có kích thước MxN.
Biểu diễn bằng sơ đồ khối:
b Xóa nhiễu Moire
void MoireRemove(Matimgin, Matimgout)
{
int M = imgin.size().height;
int N = imgin.size().width;
//1 Mo rong anh co kich thuoc PxQ
int P = getOptimalDFTSize(M);
int Q = getOptimalDFTSize(N);
//2.Them 0 vao phan mo trong
Mat f = Mat(P, Q, CV_32FC2, CV_RGB(0, 0, 0));
//3
int x, y, u, v;
for (x = 0; x < M; x++)
for (y = 0; y < N; y++)
if ((x + y) % 2 == 0)
f.at<Vec2f>(x, y)[0] = 1.0*imgin.at<uchar>(x, y);
else
f.at<Vec2f>(x, y)[0] = -1.0*imgin.at<uchar>(x, y);
//Buoc 4: Bien doi Fourier
Mat F = Mat(P, Q, CV_32FC2, CV_RGB(0, 0, 0));
dft(f, F);
//Buoc 5: Tao ham loc, va nhan H(u,v) vs F(u,v)
Mat H = Mat(P, Q, CV_32FC2, CV_RGB(0, 0, 0));
int u1 = 45, v1 = 58;
Trang 5int u2 = 40, v2 = 119;
int u3 = 86, v3 = 58;
int u4 = 82, v4 = 119;
double D01 = 5, D02 = 5, D03 = 15, D04 = 15;
double Duv, DuvTru;
double responese;
for (u = 0; u < P; u++)
for (v = 0; v < Q; v++)
{
Duv = sqrt(1.0*(u - u1)*(u - u1) + 1.0*(v - v1)*(v - v1));
DuvTru = sqrt(1.0*(u - P + u1)*(u - P + u1) + 1.0*(v - Q + v1)*(v - Q + v1)); responese = (1 / (1 + pow(D01 / Duv, 2 * 2)))*(1 / (1 + pow(D01 / DuvTru, 2 * 2)));
Duv = sqrt(1.0*(u - u2)*(u - u2) + 1.0*(v - v2)*(v - v2));
DuvTru = sqrt(1.0*(u - P + u2)*(u - P + u2) + 1.0*(v - Q + v2)*(v - Q + v2)); responese *= (1 / (1 + pow(D02 / Duv, 2 * 2)))*(1 / (1 + pow(D02 / DuvTru, 2 * 2)));
Duv = sqrt(1.0*(u - u3)*(u - u3) + 1.0*(v - v3)*(v - v3));
DuvTru = sqrt(1.0*(u - P + u3)*(u - P + u3) + 1.0*(v - Q + v3)*(v - Q + v3)); responese *= (1 / (1 + pow(D03 / Duv, 2 * 2)))*(1 / (1 + pow(D03 / DuvTru, 2 * 2)));
Duv = sqrt(1.0*(u - u4)*(u - u4) + 1.0*(v - v4)*(v - v4));
DuvTru = sqrt(1.0*(u - P + u4)*(u - P + u4) + 1.0*(v - Q + v4)*(v - Q + v4)); responese *= (1 / (1 + pow(D04 / Duv, 2 * 2)))*(1 / (1 + pow(D04 / DuvTru, 2 * 2)));
H.at<Vec2f>(u, v)[0] = responese;
}
Mat G = Mat(P, Q, CV_32FC2, CV_RGB(0, 0, 0));
mulSpectrums(F, H, G, DFT_ROWS);
//Buoc 6,7: Bien doi Fourier nguoc
Mat g = Mat(P, Q, CV_32FC2, CV_RGB(0, 0, 0));
idft(G, g, DFT_SCALE);
//doi tam anh lai
float r;
for (x = 0; x < M; x++)
for (y = 0; y < N; y++)
{
if ((x + y) % 2 == 0)
r = g.at<Vec2f>(x, y)[0];
else
r = -g.at<Vec2f>(x, y)[0];
if (r < 0)
r = 0;
if (r>L - 1)
r = L - 1;
imgout.at<uchar>(x, y) = (uchar)r;
}
}
Trang 6Câu 4: Xây dựng và cài đặt thuật toán nhận dạng khuôn mặt dùng phương pháp khuôn mặt riêng (eigenface)
Các bước nhận dạng khuôn mặt.
Bước 1: Phát hiện khuôn măt dùng thuật toán và file xml có sẵn trong openCV Dùng Detect and Display().
Bước 2: Tạo cơ sở dữ liệu gồm 15 mặt, trong đó 10 mặt dùng để học, 5 mặt dùng để nhận dạng.
Bước 3: Nhận dạng dùng eigenface.
void detectAndDisplay(Mat frame, int c);
void detectAndDisplayAndRecognition(Mat frame, int c);
String face_cascade_name = "haarcascade_frontalface_alt.xml";
CascadeClassifier face_cascade;
string window_name = "Capture - Face detection";
RNG rng(12345);
Ptr<FaceRecognizer> model;
int GetImage(void)
{
VideoCapture capture(0);
Mat frame;
// 1 Load the cascades
if (!face_cascade.load(face_cascade_name)){ printf(" (!)Error loading\n"); return -1; };
// 2 Read the video stream
if (capture.isOpened())
{
namedWindow(window_name, WINDOW_AUTOSIZE);
waitKey(1000);
for (;;) {
capture >> frame;
int c = waitKey(10);
if (c == 27)
break; // 3 Apply the classifier to the frame
if (!frame.empty()) {
detectAndDisplay(frame,c);
} else {
printf(" (!) No captured frame Break!");
break; }
} }
return 0;
}
Trang 7void detectAndDisplay(Matframe, intc)
{
std::vector<Rect> faces;
Mat frame_gray;
static int count = 1;
char filename[64];
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);
// Detect faces
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));
for (size_t i = 0; i < faces.size(); i++)
{
Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2); ellipse(frame, center, Size(faces[i].width / 2, faces[i].height / 2), 0, 0, 360, Scalar(255, 0, 255), 2, 8, 0);
Mat faceROI = frame_gray(faces[i]);
if (c == 'A' || c == 'a') {
sprintf(filename, "data\\Linh\\%02d.bmp", count++);
imwrite(filename, faceROI);
} }
// Show what you got
imshow(window_name, frame);
}
void Training(void)
{
vector<Mat> images;
vector<int> labels;
char filename[64];
for (int i = 1; i <= 10; i++)
{
sprintf(filename, "data\\Duyen\\%02d.bmp", i);
Mat img = imread(filename, CV_LOAD_IMAGE_GRAYSCALE);
resize(img, img, Size(100, 100));
images.push_back(img);
labels.push_back(1);
}
for (int i = 1; i <= 10; i++)
{
sprintf(filename, "data\\Anh\\%02d.bmp", i);
Mat img = imread(filename, CV_LOAD_IMAGE_GRAYSCALE);
resize(img, img, Size(100, 100));
images.push_back(img);
labels.push_back(2);
}
for (int i = 1; i <= 10; i++)
{
Trang 8sprintf(filename, "data\\Linh\\%02d.bmp", i);
Mat img = imread(filename, CV_LOAD_IMAGE_GRAYSCALE);
resize(img, img, Size(100, 100));
images.push_back(img);
labels.push_back(3);
}
//traning
model = createEigenFaceRecognizer();
model->train(images, labels);
model->save("face.xml");
return;
}
void detectAndDisplayAndRecognition(Matframe, intc)
{
std::vector<Rect> faces;
Mat frame_gray;
static int count = 1;
char s[64];
int predictLabel;
double confidence;
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);
// Detect faces
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));
for (size_t i = 0; i < faces.size(); i++)
{
Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2); ellipse(frame, center, Size(faces[i].width / 2, faces[i].height / 2), 0, 0, 360, Scalar(255, 0, 255), 2, 8, 0);
Mat faceROI = frame_gray(faces[i]);
if (c == 'A' || c == 'a') {
resize(faceROI, faceROI, Size(100, 100));
predictLabel = -1;
confidence = 0.0;
model->predict(faceROI, predictLabel, confidence);
sprintf(s, "%d %.2f", predictLabel, confidence);
putText(faceROI, s, Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, CV_RGB(255, 255, 255));
imshow("Recognition", faceROI);
if (predictLabel == 1) {
sprintf(s, "Duyen %.2f", confidence);
putText(faceROI, s, Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, CV_RGB(255, 255, 255));
imshow("Recognition", faceROI);
Trang 9} else if (predictLabel == 2) {
sprintf(s, "Anh %.2f", confidence);
putText(faceROI, s, Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, CV_RGB(255, 255, 255));
imshow("Recognition", faceROI);
} else {
sprintf(s, "Linh %.2f", confidence);
putText(faceROI, s, Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, CV_RGB(255, 255, 255));
imshow("Recognition", faceROI);
} }
}
// Show what you got
imshow(window_name, frame);
}
int Recognition(void)
{
namedWindow("Recognition", WINDOW_AUTOSIZE);
model = createEigenFaceRecognizer();
model->load("face.xml");
VideoCapture capture(0);
Mat frame;
// 1 Load the cascades
if (!face_cascade.load(face_cascade_name)){ printf(" (!)Error loading\n"); return -1; };
// 2 Read the video stream
if (capture.isOpened())
{
namedWindow(window_name, WINDOW_AUTOSIZE);
waitKey(1000);
for (;;) {
capture >> frame;
int c = waitKey(10);
if (c == 27)
break; // 3 Apply the classifier to the frame
if (!frame.empty()) {
detectAndDisplayAndRecognition(frame, c);
} else {
printf(" (!) No captured frame Break!");
break;
Trang 10} }
}
return 0;
}
int main(void)
{
//GetImage(); //không cần hàm này cũng được…
//Training();
Recognition();
return 0;
}
Phương pháp phát hiện và nhận dạng đối tượng trong ảnh, cụ thể là nhận dạng khuôn mặt
- Có 2 bước chính là phát hiện và nhận dạng
B1: phát hiện - detect
Có 3 phương pháp trích đặc điểm thông dụng là Haar-like, LBP (Local Binary Pattern) và HOG (Histogram Orient Gradient)
Ta phải tạo ra file xml Phương pháp tạo ra file xml Ta dùng công cụ Haar-kit ở
http://robotik.inflomatik.info
a/ Ta phải có khoảng 1500 ảnh chứa đối tượng cần nhận dạng, ta gọi là ảnh dương, đối tượng ở trong nền ra
phức tạp
2000 ảnh không chứa đối tượng (ảnh nền), và ta gọi là ảnh âm Dùng file objectmarker.exe để đánh dấu ảnh dương, kết quả lưu trong file info.txt
tenfil 1 x y width heigh b/ Dùng createsamples.exe hoặc opencv_createsamples.exe
(C:\opencv\build\x86\VC10\bin) để tạo ra
file hand.vec
c/ Dùng opencv_traincascade.exe để đọc ảnh dương đã đánh dấu và ảnh âm để tạo ra file xml
thời gian chạy bước c khoảng 1 ngày rưỡi trên máy P 4, 3.2GHz
B2: Nhận dạng
Nói rồi bài nhận dạng bàn tay hôm trước @~@ OMG!!!!
5 ANH NHIN THANG QUA TRA QUA PHAI NHIN LEN NHIN XUONG
khoanh khuon mat roi moi nhan chu a de chup
void detectAndDisplay( Mat frame, int c);
void detectAndDisplayAndRecognation( Mat frame, int c);
Ptr < FaceRecognizer > model;
String face_cascade_name = "haarcascade_frontalface_alt.xml";
//String eyes_cascade_name = "haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_cascade;
//CascadeClassifier eyes_cascade;
string window_name = "Capture - Face detection";
RNG rng(12345);
Trang 11int GetImage( void )
{
VideoCapture capture(0);
Mat frame;
if (!face_cascade.load(face_cascade_name)){ printf(" (!)Error loading\n"); return -1; };
//if (!eyes_cascade.load(eyes_cascade_name)){ printf(" (!)Error loading\n"); return -1; };
if (capture.isOpened())
{
namedWindow(window_name, WINDOW_AUTOSIZE );
for (;;) {
capture >> frame;
int c = waitKey(10);
if (c == 27)
break ;
if (!frame.empty())
detectAndDisplay(frame,c);
else
{
printf(" (!) No captured frame Break!");
break ; }
} }
return 0;
}
void detectAndDisplay( Mat frame , int c )
{
std:: vector < Rect > faces;
Mat frame_gray;
static int count = 13;
char filename[64];
cvtColor( frame , frame_gray, COLOR_BGR2GRAY );
equalizeHist(frame_gray, frame_gray);
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE , Size (30, 30));
for ( size_t i = 0; i < faces.size(); i++)
{
Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2);
ellipse( frame , center, Size (faces[i].width / 2, faces[i].height / 2), 0, 0, 360, Scalar (255, 0, 255), 2, 8, 0);
Mat faceROI = frame_gray(faces[i]);
if ( c == 'A' || c == 'a'){
sprintf(filename, "data\\DaiDong\\%02d.bmp", count++);
imwrite(filename, faceROI);
} }
imshow(window_name, frame );
}
void detectAndDisplayAndRecognation( Mat frame , int c )
{
std:: vector < Rect > faces;
Mat frame_gray;
static int count = 13;