日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

访问图像中每个像素的值

發布時間:2025/3/21 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 访问图像中每个像素的值 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載請注明出處:http://blog.csdn.net/xiaowei_cqu/article/details/7557063

!!此篇是基于IplImage* (C接口或者說2.1之前版本的接口,新的Mat的訪問方式請參考博文: 《訪問Mat圖像中每個像素的值》)

IplImage是OpenCV中CxCore部分基礎的數據結構,用來表示圖像,其中Ipl是Intel Image Processing Library的簡寫。以下是IplImage的結構分析(來自OpenCV中文網站:http://www.opencv.org.cn/index.php/Cxcore%E5%9F%BA%E7%A1%80%E7%BB%93%E6%9E%84#IplImage)

[cpp]?view plaincopy
  • typedef?struct?_IplImage??
  • ????{??
  • ????????int??nSize;?????????/*?IplImage大小?*/??
  • ????????int??ID;????????????/*?版本?(=0)*/??
  • ????????int??nChannels;?????/*?大多數OPENCV函數支持1,2,3?或?4?個通道?*/??
  • ????????int??alphaChannel;??/*?被OpenCV忽略?*/??
  • ????????int??depth;?????????/*?像素的位深度:?IPL_DEPTH_8U,?IPL_DEPTH_8S,?IPL_DEPTH_16U,?
  • ???????????????????????????????IPL_DEPTH_16S,?IPL_DEPTH_32S,?IPL_DEPTH_32F?and?IPL_DEPTH_64F?可支持?*/??
  • ????????char?colorModel[4];?/*?被OpenCV忽略?*/??
  • ????????char?channelSeq[4];?/*?同上?*/??
  • ????????int??dataOrder;?????/*?0?-?交叉存取顏色通道,?1?-?分開的顏色通道.?
  • ???????????????????????????????cvCreateImage只能創建交叉存取圖像?*/??
  • ????????int??origin;????????/*?0?-?頂—左結構,?
  • ???????????????????????????????1?-?底—左結構?(Windows?bitmaps?風格)?*/??
  • ????????int??align;?????????/*?圖像行排列?(4?or?8).?OpenCV?忽略它,使用?widthStep?代替?*/??
  • ????????int??width;?????????/*?圖像寬像素數?*/??
  • ????????int??height;????????/*?圖像高像素數*/??
  • ????????struct?_IplROI?*roi;/*?圖像感興趣區域.?當該值非空只對該區域進行處理?*/??
  • ????????struct?_IplImage?*maskROI;?/*?在?OpenCV中必須置NULL?*/??
  • ????????void??*imageId;?????/*?同上*/??
  • ????????struct?_IplTileInfo?*tileInfo;?/*同上*/??
  • ????????int??imageSize;?????/*?圖像數據大小(在交叉存取格式下imageSize=image->height*image->widthStep),單位字節*/??
  • ????????char?*imageData;??/*?指向排列的圖像數據?*/??
  • ????????int??widthStep;???/*?排列的圖像行大小,以字節為單位?*/??
  • ????????int??BorderMode[4];?/*?邊際結束模式,?被OpenCV忽略?*/??
  • ????????int??BorderConst[4];?/*?同上?*/??
  • ????????char?*imageDataOrigin;?/*?指針指向一個不同的圖像數據結構(不是必須排列的),是為了糾正圖像內存分配準備的?*/??
  • ????}??
  • ????IplImage;??

  • 直接訪問:

    對我們來說比較重要的兩個元素是:char *imageData以及widthStep。imageData存放圖像像素數據,而widStep類似CvMat中的step,表示以字節為單位的行數據長度。

    一個m*n的單通道字節型圖像,其imageData排列如下:


    如果我們要遍歷圖像中的元素,只需:

    [cpp]?view plaincopy
  • IplImage*?img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);??
  • uchar*?tmp;??
  • for(int?i=0;i<img->height;i++)??
  • ????for(int?j=0;j<img->width;j++)??
  • ????????*tmp=((uchar?*)(img->imageData?+?i*img->widthStep))[j];??
  • 這種直接訪問的方法速度快,但容易出錯,我們可以通過定義指針來訪問。即:

    [cpp]?view plaincopy
  • IplImage*?img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);??
  • ucha*?data=(uchar?*)img->imageData;??
  • int?step?=?img->widthStep/sizeof(uchar);??
  • uchar*?tmp;??
  • for(int?i=0;i<img->height;i++)??
  • ????for(int?j=0;j<img->width;j++)??
  • ????????*tmp=data[i*step+j];??
  • 而多通道(三通道)字節圖像中,imageData排列如下:

    其中(Bi,Bj)(Gi,Gj)(Ri,Rj)表示圖像(i,j)處BGR分量的值。使用指針的遍歷方法如下:

    [cpp]?view plaincopy
  • IplImage*?img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);??
  • IplImage*?img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);??
  • uchar*?data=(uchar?*)img->imageData;??
  • int?step?=?img->widthStep/sizeof(uchar);??
  • int?channels?=?img->nChannels;??
  • uchar?*b,*g,*r;??
  • for(int?i=0;i<img->height;i++)??
  • ?????for(int?j=0;j<img->width;j++){??
  • ???????????*b=data[i*step+j*chanels+0];??
  • ???????????*g=data[i*step+j*chanels+1];??
  • ???????????*r=data[i*step+j*chanels+2];??
  • ??????}??
  • *如果要修改某像素值,則直接賦值。

    使用cvGet2D()函數訪問:

    cvGet*D系列函數可以用來返回特定位置的數組元素(一般使用cvGet2D),原型如下: [cpp]?view plaincopy
  • CvScalar?cvGet1D(?const?CvArr*?arr,?int?idx0?);??
  • CvScalar?cvGet2D(?const?CvArr*?arr,?int?idx0,?int?idx1?);??
  • CvScalar?cvGet3D(?const?CvArr*?arr,?int?idx0,?int?idx1,?int?idx2?);??
  • CvScalar?cvGetND(?const?CvArr*?arr,?int*?idx?);??
  • idx0,idx1,idx2分別用來指示元素數組下標,即cvGet2D返回(idx0,idx1)處元素的值。
    因此,單通道圖像像素訪問方式如下: [cpp]?view plaincopy
  • IplImage*?img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);??
  • double?tmp;??
  • for(int?i=0;i<img->height;i++)??
  • ????for(int?j=0;j<img->width;j++)??
  • ????????tmp=cvGet2D(img,i,j).val[0];??
  • 多通道字節型/浮點型圖像: [cpp]?view plaincopy
  • IplImage*?img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);??
  • double?tmpb,tmpg,bmpr;??
  • for(int?i=0;i<img->height;i++)??
  • ????for(int?j=0;j<img->width;j++){??
  • ????????tmpb=cvGet2D(img,i,j).val[0];??
  • ????????tmpg=cvGet2D(img,i,j).val[1];??
  • ????????tmpr=cvGet2D(img,i,j).val[2];??
  • ????}??
  • 如果是修改元素的值,可用cvSet*D(一般是cvSet2D)函數: [cpp]?view plaincopy
  • void?cvSet1D(?CvArr*?arr,?int?idx0,?CvScalar?value?);??
  • void?cvSet2D(?CvArr*?arr,?int?idx0,?int?idx1,?CvScalar?value?);??
  • void?cvSet3D(?CvArr*?arr,?int?idx0,?int?idx1,?int?idx2,?CvScalar?value?);??
  • void?cvSetND(?CvArr*?arr,?int*?idx,?CvScalar?value?);??
  • 這種方法對于任何圖像的訪問方式是一樣的,比較簡單,但效率較低,不推薦使用。

    總結

    以上是生活随笔為你收集整理的访问图像中每个像素的值的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。