Top Ad unit 728 × 90

Latest news

recent

Các phương pháp truy xuất pixel dùng OpenCV

Ảnh được cấu tạo bởi các pixel, điểm ảnh, chính vì lẽ đó mà có thể nói xử lý ảnh là quá trình xử lý trên điểm ảnh. Làm sao để làm việc một cách hiệu quả, truy xuất, cập nhật nhanh nhất, thuận tiện nhất các giá trị này là vấn đề căn cơ cần phải học khi nhập môn.
Giả sử bạn cần truy xuất vào kênh màu thứ K của điểm ảnh ở dòng i và cột thứ j. Chỉ mục i của dòng thuộc vào khoảng [0, height - 1]. Chỉ mục j của cột nằm trong đoạn [0, width-1]. Chỉ mục K của kênh màu thì giới hạn trong [0, nchannels - 1].Tôi đưa ra các thông tin khoảng chạy này với ngụ ý nếu bạn sử dụng các phương pháp dưới đây trong vòng lặp thích hợp bạn có thể duyệt toàn các điểm trong ảnh.
  • Phương pháp truy xuất gián tiếp (Indirect access): (đánh giá: thông dụng, không hiệu quả, truy xuất đến bất kì định dạng nào được hỗ trợ bởi OpenCV)
    • Dùng cho hình chỉ có 1byte / 1 kênh màu (single-channel byte image):
      IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
      CvScalar s;
      s=cvGet2D(img,i,j); // get the (i,j) pixel value
      printf("intensity=%f\n",s.val[0]);
      s.val[0]=111;
      cvSet2D(img,i,j,s); // set the (i,j) pixel value
    • Dùng cho hình đa kênh với mỗi kênh là 1 byte hay 1 float (multi-channel float (or byte) image):
      IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
      CvScalar s;
      s=cvGet2D(img,i,j); // get the (i,j) pixel value
      printf("B=%f, G=%f, R=%f\n",s.val[0],s.val[1],s.val[2]);
      s.val[0]=111;
      s.val[1]=111;
      s.val[2]=111;
      cvSet2D(img,i,j,s); // set the (i,j) pixel value
  • Truy xuất trực tiếp: (Hiệu quả, dễ tìm ẩn lỗi)
    • Dùng cho single-channel byte image:
      IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
      ((uchar *)(img->imageData + i*img->widthStep))[j]=111;
    • Dùng cho multi-channel byte image:
      IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
      ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B
      ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G
      ((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R
    • Dùng cho multi-channel float image:
      IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
      ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B
      ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G
      ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R
  • Truy xuất trực tiếp sử dụng pointer: (Đơn giản, hiệu quả)
    • Dùng cho single-channel byte image:
      IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
      int height     = img->height;
      int width      = img->width;
      int step       = img->widthStep/sizeof(uchar);
      uchar* data    = (uchar *)img->imageData;
      data[i*step+j] = 111;
    • Dùng cho multi-channel byte image:
      IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
      int height     = img->height;
      int width      = img->width;
      int step       = img->widthStep/sizeof(uchar);
      int channels   = img->nChannels;
      uchar* data    = (uchar *)img->imageData;
      data[i*step+j*channels+k] = 111;
    • Dùng cho multi-channel float image (assuming a 4-byte alignment):
      IplImage* img  = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
      int height     = img->height;
      int width      = img->width;
      int step       = img->widthStep/sizeof(float);
      int channels   = img->nChannels;
      float * data    = (float *)img->imageData;
      data[i*step+j*channels+k] = 111;
  • Truy xuất trực tiếp dùng c++ wrapper: (Đơn giản và truy xuất hiệu quả)
    • Định nghĩa a c++ wrapper cho single-channel byte images, multi-channel byte images, and multi-channel float images:
      template class Image
      {
        private:
        IplImage* imgp;
        public:
        Image(IplImage* img=0) {imgp=img;}
        ~Image(){imgp=0;}
        void operator=(IplImage* img) {imgp=img;}
        inline T* operator[](const int rowIndx) {
          return ((T *)(imgp->imageData + rowIndx*imgp->widthStep));}
      };
      
      typedef struct{
        unsigned char b,g,r;
      } RgbPixel;
      
      typedef struct{
        float b,g,r;
      } RgbPixelFloat;
      
      typedef Image       RgbImage;
      typedef Image  RgbImageFloat;
      typedef Image  BwImage;
      typedef Image          BwImageFloat;
    • Đối với single-channel byte image:
      IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
      BwImage imgA(img);
      imgA[i][j] = 111;
    • Đối với multi-channel byte image:
      IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
      RgbImage  imgA(img);
      imgA[i][j].b = 111;
      imgA[i][j].g = 111;
      imgA[i][j].r = 111;
    • Đối với multi-channel float image:
      IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
      RgbImageFloat imgA(img);
      imgA[i][j].b = 111;
      imgA[i][j].g = 111;
      imgA[i][j].r = 111;
  • BONUS: Ứng dụng phương pháp truy xuất để duyệt image data
void VnPPixelAccess(IplImage *image) {
      int nl= image->height; // number of lines
      int nc= image->width * image->nChannels; // total number of element per line
      int step= image->widthStep; // effective width
      // get the pointer to the image buffer
      unsigned char *data= reinterpret_cast (image->imageData);
      for (int i=0; i < nl; i++) {
            for (int j=0; j < nc; j += nChannels) {
            // process each pixel ---------------------
                  for(int k=0; k < image->nChannels; k++) {
                         data[j + k]= giá trị mà bạn muốn :p;                       
                  }
            // end of pixel processing ----------------
            } // end of line
                  
            data+= step;  // next line
      }
}



Binh Nguyen - Bioz
Các phương pháp truy xuất pixel dùng OpenCV Reviewed by Bioz Nguyen on 8:11:00 AM Rating: 5
All Rights Reserved by IEEV © 2009 - 2016
Powered By Blogger, Designed by Sweetheme

Contact Form

Name

Email *

Message *

Powered by Blogger.