Thứ Hai, 29 tháng 9, 2014

ÔN TẬP CHUYÊN ĐỀ 1 - 2014


Câu 1: Cân bằng histogram.
a.  Viết công thức
·         Mục đích của cân bằng histogram là làm cho histogram đồng đều. Khi đó ta làm tăng được độ tương phản của ảnh.
·         Cân bằng histogram được cho bằng phương trình: s=T(r)=(L-1)  
với 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)  
với k= 0,1,2,…,L-1
b.  Lập trình
void HistogramEqulization(Mat imgin, Mat imgout)

{

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]=1.0*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];
}

for(x=0;x<M;x++) for(y=0;y<N;y++)

{
r=imgin.at<uchar>(x,y); imgout.at<uchar>(x,y)=uchar((L-1)*s[r]);
}

return;

}
c. Hàm trong openCV.

equalizeHist(imgin, imgout);

Câu 2: Lọc median. (lọc trung vị)
a.  Viết công thức
Mô tả thuật toán như sau: rê ma trận trên ảnh đến khi nào đủ 9 giá trị trên ma trận 3x3thì tiến hành sắp xếp ma trận này tăng dần từ trái qua phải từ trên xuống dưới, vào thay phần tử chính giữa cũ bằng phần tử chính giữa mới.

b.  Lập trình
        void Sort(Mat w)

{

int size=w.size().height*w.size().width;
int i,j;

uchar temp;
for(i=0;i<size-1;i++)
for(j=i+1;j<size;j++)

if(w.data[i]>w.data[j])
{

temp=w.data[i];

w.data[i]=w.data[j];

w.data[j]=temp;
}
}

void MedianFilter(Mat imgin,Mat imgout)
{

int M=imgin.size().height;
int N=imgin.size().width;
int x,y,s,t;
uchar r,sd;

int m=5,n=5;
int a=m/2,b=n/2;

Mat w=Mat(m,n,CV_8UC1,CV_RGB(0,0,0));

for(x=a;x<M-a;x++)
for(y=b;y<N-b;y++)

{

for(s=-a;s<=a;s++)
for(t=-b;t<=b;t++)
w.at<uchar>(s+a,t+b)=imgin.at<uchar>(x+s,y+t);

Sort(w);
imgout.at<uchar>(x,y)=w.at<uchar>(a,b);
}

}
c. Hàm trong openCV.
          medianBlur(imgin,imgout,5);

Câu 3: Lọc tuyến tính
a.  Viết công thức
                Tổng quát lọc trong không gian được cho bằng phương trình :
g(x,y)=
Trong đó :
mxn là kích thước của bộ lọc, m và n thường là số lẻ để bộ lọc có phần tử trung tâm.
a=m/2  và b=n/2 là kích thước nữa bộ lọc.
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 là bộ lọc trung bình.
Ví dụ: mặt nạ lọc trung bình và mặt nạ Gauss:
1
1
1
1
1
1
1
1
1
x
1
2
1
2
4
2
1
2
1


b.  Lập trình
          void MyFilter2D(Mat imgin, Mat imgout, Mat w)
{
       int m = w.size().height;
       int n = w.size().width;
       int a=m/2, b=n/2;
       int M = imgin.size().height;
       int N = imgin.size().width;
       int x, y, s, t;
       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;
}

void MySmooth(Mat imgin, Mat imgout)
{
       int m=35, n=35;
       Mat w = Mat(m,n,CV_32F);
       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);
              Or
filter2d(imgin,imgout,CV_8U,w);
       return;
}





Câu 4: Các bước lọc trong miền tần số
Lọc ảnh trong miền tần số gồm 7 bước sau đây:
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 vào phần mở rộng, ta được ảnh fp(x,y).
Bước 3: Nhân fp(x,y) với (-1)x+y để dời F(0,0) vào tâm ảnh.
Bước 4: Biến đổi Fourier của ảnh ở Bước 3 ta được F(u,v).
Bước 5: Cho hàm lọc có giá trị thực H(u,v) đối xứng qua tâm (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:














Câu 5: Lọc khe để xoá nhiễu Moire
void NotchFiltering(Mat imgin, Mat imgout)
{
      int M = imgin.size().height;
      int N = imgin.size().width;
     
      // Buoc 1, 2, 3
      int P = getOptimalDFTSize(M);
      int Q = getOptimalDFTSize(N);
      Mat f = Mat(P,Q,CV_32FC2,CV_RGB(0,0,0));
      int x, y;
      for (x=0; x<M; x++)
            for (y=0; y<N; y++)
                  if ((x+y)%2 == 0)
                        f.at<Vec2f>(x,y)[0] = imgin.at<uchar>(x,y);
                  else
                        f.at<Vec2f>(x,y)[0] = -imgin.at<uchar>(x,y);

      // Buoc 4
      Mat F = Mat(P,Q,CV_32FC2,CV_RGB(0,0,0));
      dft(f,F);

      // Buoc 5
      Mat H = Mat(P,Q,CV_32FC2,CV_RGB(0,0,0));
      double D01 = 12, D02 = 12, D03 = 5, D04 = 5;
      double Dk, D_k;
      int u, v;
      int u1 = 164, v1 = 121;
      int u2 = 168, v2 = 61;
      int u3 = 210, v3 = 61;
      int u4 = 206, v4 = 122;
      int n = 4;
      for (u=0; u<P; u++)
            for (v=0; v<Q; v++) {
            Dk  = sqrt(1.0*(u-u1)*(u-u1)+1.0*(v-v1)*(v-v1));
            D_k = sqrt(1.0*(u-(P-u1))*(u-(P-u1))+1.0*(v-(Q-v1))*(v-(Q-v1)));
            H.at<Vec2f>(u,v)[0] = 1.0/(1.0+pow(D01/Dk,2*n))*1.0/(1.0+pow(D01/D_k,2*n));
           
Dk  = sqrt(1.0*(u-u2)*(u-u2)+1.0*(v-v2)*(v-v2));
            D_k = sqrt(1.0*(u-(P-u2))*(u-(P-u2))+1.0*(v-(Q-v2))*(v-(Q-v2)));
            H.at<Vec2f>(u,v)[0] *= 1.0/(1.0+pow(D02/Dk,2*n))*1.0/(1.0+pow(D02/D_k,2*n));

            Dk  = sqrt(1.0*(u-u3)*(u-u3)+1.0*(v-v3)*(v-v3));
            D_k = sqrt(1.0*(u-(P-u3))*(u-(P-u3))+1.0*(v-(Q-v3))*(v-(Q-v3)));
            H.at<Vec2f>(u,v)[0] *= 1.0/(1.0+pow(D03/Dk,2*n))*1.0/(1.0+pow(D03/D_k,2*n));

            Dk  = sqrt(1.0*(u-u4)*(u-u4)+1.0*(v-v4)*(v-v4));
            D_k = sqrt(1.0*(u-(P-u4))*(u-(P-u4))+1.0*(v-(Q-v4))*(v-(Q-v4)));
            H.at<Vec2f>(u,v)[0] *= 1.0/(1.0+pow(D04/Dk,2*n))*1.0/(1.0+pow(D04/D_k,2*n));
            }
           
      Mat G = Mat(P,Q,CV_32FC2,CV_RGB(0,0,0));
      mulSpectrums(F,H,G,DFT_ROWS);

      // Buoc 6, 7
      Mat g = Mat(P,Q,CV_32FC2,CV_RGB(0,0,0));
      idft(G,g,DFT_SCALE);
      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;
            }
      return;
}

























Câu 6: Đếm số hạt gạo và phân ngưỡng
Code đếm số hạt gạo
          void CountRice(Mat imgin,Mat imgout)
{
      Mat temp = Mat(imgin.size(),CV_8UC1);
      Mat w = getStructuringElement(MORPH_ELLIPSE,Size(81,81));
      morphologyEx(imgin,temp,MORPH_TOPHAT,w);
      double max;
      minMaxLoc(temp,0,&max);
      threshold(temp,temp,0.4*max,255,THRESH_BINARY);
// 0.9*max danh cho diem suong
      medianBlur(temp,temp,5);
      int fromTo[] = {0,0,0,1,0,2};
      mixChannels(&temp,1,&imgout,1,fromTo,3);

      int x, y, M, N;
      M = imgout.size().height;
      N = imgout.size().width;
      Vec3b p;
      uchar r, g, b;
      int color = 100;
      for (x=0; x<M; x++)
            for (y=0; y<N; y++) {
                  p = imgout.at<Vec3b>(x,y);
                  if (p[0] == L-1 && p[1] == L-1 && p[2] == L-1) {
                        r = color%256;
                        g = (color/256)%256;
                        b = ((color/256)/256)%256;
                        floodFill(imgout,Point(y,x),CV_RGB(r,g,b));
                        color++;
                  }
            }

      int k, mang[1000];
      for (k=0; k<1000; k++)
            mang[k] = 0;

      for (x=0; x<M; x++)
            for (y=0; y<N; y++) {
                  p = imgout.at<Vec3b>(x,y);
                  r = p[2];
                  g = p[1];
                  b = p[0];
                  k = r + g*256 + b*256*256;
                  if (k > 0)
                        mang[k]++;
            }
     
      FILE *fp = fopen("ThongKe.txt","wt");
      fprintf(fp,"Co %d hot gao\n",color-100);
      for (k=0; k<1000; k++)
            if (mang[k] > 0)
                  fprintf(fp,"Mau %3d co %3d pixel\n",k,mang[k]);
      fclose(fp);
     
      char buffer[256];
      sprintf(buffer,"Co %d hot gao",color-100);
      putText(imgout,buffer,Point(0,25),FONT_HERSHEY_DUPLEX,0.7,CV_RGB(0,255,0));
      return;
}

Câu 7: Xây dựng và cài đặt thuật toán biến đổi Hough
Mục đích của biến đổi Hough là để phát hiện ra đường thẳng và đường tròn, hoặc đường bất kì. Thông thường nhất dùng biến đổi Hough để phát hiện đường thẳng.
Cho điểm xi, yi ở trong mặt phẳng x, y.
Phương trình đường thẳng y=ax+b.
Nếu đường thẳng đi qua điểm (xi,yi) thì nó sẽ là yi=ax­­I +b.
Khi cho a, b thay đổi thì có rất nhiều đường thẳng đi qua
(xi,yi). Ta có thêm một điểm (xj,yj) nữa thì cũng có vô số đường thẳng đi qua (xj,y).
Như vậy sẽ có một đường thẳng đi qua hai điểm (xi,yi) và (xj,yj).
Và đường thẳng đó sẽ có a, b giống nhau.
Yi= axi+b
Yj= axj+b
                               
Dùng mặt phẳng a, b không biết được kích thước ảnh bao nhiêu vì cho ảnh chạy từ -∞, ∞ và b: -∞, ∞
Để khắc phục a, b có thể ra tới ∞, thì ta chuyển phương trình đường thẳng qua tọa độ cực:
Do các điểm ảnh có tọa độ x dương, y dương nên  chạy từ -900 đến 90và phạm vi của  là , trong đó D là khoảng cách xa nhất giữa 2 góc đối diện ở trong ảnh.
Lập trình:
void ImageRotation(Mat imgin, Mat imgout)
{
            vector<Vec2f> s_lines;
            HoughLines(imgin, s_lines, 1, CV_PI/180, 100, 0, 0 );
            /// Show the result
            float r, t, rmax, tmax;
            rmax = s_lines[0][0];
            tmax = s_lines[0][1];
            for( size_t i = 0; i < s_lines.size(); i++ ) {
                        r = s_lines[i][0];
                        t = s_lines[i][1];
                        if (r > rmax) {
                                    rmax = r;
                                    tmax = t;
                        }
            }
            int M = imgin.size().height;
            int N = imgin.size().width;
            int x, y;
            int xr = 0, yr = 0;
            for (x=0; x<M; x++)
                        for (y=0; y<N; y++) {
                                    r = imgin.at<uchar>(x,y);
                                    if (r == L-1)
                                                if (x > xr) {
                                                            xr = x;
                                                            yr = y;
                                                }
                        }

            Mat rot_mat(2,3,CV_32FC1);
            Point center = Point(yr,xr);
            double angle = (tmax-CV_PI/2)*180/CV_PI;
            double scale = 1;
            rot_mat = getRotationMatrix2D(center,angle,scale);
            warpAffine(imgin,imgout,rot_mat,imgout.size());
            return;
}







Câu 8: Nhận dạng khuôn mặt
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.

Lập trình
int RecognitionOffLine(void)
{
            vector<Mat> images;
            vector<int> labels;
            char filename[64];
            for (int i=1; i<=10; i++) {
                        sprintf(filename,"data\\ThayDuc\\%02d.jpg",i);
                        Mat img = imread(filename,CV_LOAD_IMAGE_GRAYSCALE);
                        resize(img,img,Size(150,150));
                        images.push_back(img);
                        labels.push_back(1);
            }

            for (int i=1; i<=11; i++) {
                        sprintf(filename,"data\\Thuong\\%02d.jpg",i);
                        Mat img = imread(filename,CV_LOAD_IMAGE_GRAYSCALE);
                        resize(img,img,Size(150,150));
                        images.push_back(img);
                        labels.push_back(2);
            }

            for (int i=1; i<=10; i++) {
                        sprintf(filename,"data\\Minh\\%02d.jpg",i);
                        Mat img = imread(filename,CV_LOAD_IMAGE_GRAYSCALE);
                        resize(img,img,Size(150,150));
                        images.push_back(img);
                        labels.push_back(3);
            }

            Ptr<FaceRecognizer> model = createEigenFaceRecognizer();
            model->train(images,labels);
            Mat test = imread("test\\ThayDuc\\01.jpg",CV_LOAD_IMAGE_GRAYSCALE);
            resize(test,test,Size(150,150));
            int predictedLabel = model->predict(test);
            return 0;

}          

Không có nhận xét nào:

Đăng nhận xét