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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

访问Mat中每个像素的值

發(fā)布時(shí)間:2025/4/16 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 访问Mat中每个像素的值 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Color Reduce

還是使用經(jīng)典的Reduce Color的例子,即對(duì)圖像中的像素表達(dá)進(jìn)行量化。如常見(jiàn)的RGB24圖像有256×256×256中顏色,通過(guò)Reduce Color將每個(gè)通道的像素減少8倍至256/8=32種,則圖像只有32×32×32種顏色。假設(shè)量化減少的倍數(shù)是N,則代碼實(shí)現(xiàn)時(shí)就是簡(jiǎn)單的value/N*N,通常我們會(huì)再加上N/2以得到相鄰的N的倍數(shù)的中間值,最后圖像被量化為(256/N)×(256/N)×(256/N)種顏色。

方法零:.ptr和[]操作符

Mat最直接的訪問(wèn)方法是通過(guò).ptr<>函數(shù)得到一行的指針,并用[]操作符訪問(wèn)某一列的像素值。

[cpp]?view plaincopy
  • //?using?.ptr?and?[]??
  • void?colorReduce0(cv::Mat?&image,?int?div=64)?{??
  • ??????int?nr=?image.rows;?//?number?of?rows??
  • ??????int?nc=?image.cols?*?image.channels();?//?total?number?of?elements?per?line??
  • ??????for?(int?j=0;?j<nr;?j++)?{??
  • ??????????uchar*?data=?image.ptr<uchar>(j);??
  • ??????????for?(int?i=0;?i<nc;?i++)?{??
  • ??????????????????data[i]=?data[i]/div*div?+?div/2;??
  • ????????????}????????????????????
  • ??????}??
  • }??

  • 方法一:.ptr和指針操作

    除了[]操作符,我們可以移動(dòng)指針*++的組合方法訪問(wèn)某一行中所有像素的值。

    [cpp]?view plaincopy
  • //?using?.ptr?and?*?++???
  • void?colorReduce1(cv::Mat?&image,?int?div=64)?{??
  • ??????int?nr=?image.rows;?//?number?of?rows??
  • ??????int?nc=?image.cols?*?image.channels();?//?total?number?of?elements?per?line??
  • ??????for?(int?j=0;?j<nr;?j++)?{??
  • ??????????uchar*?data=?image.ptr<uchar>(j);??
  • ??????????for?(int?i=0;?i<nc;?i++)?{??
  • ?????????????????*data++=?*data/div*div?+?div/2;??
  • ????????????}?//?end?of?row???????????????????
  • ??????}??
  • }??

  • 方法二:.ptr、指針操作和取模運(yùn)算

    方法二和方法一的訪問(wèn)方式相同,不同的是color reduce用模運(yùn)算代替整數(shù)除法

    [cpp]?view plaincopy
  • //?using?.ptr?and?*?++?and?modulo??
  • void?colorReduce2(cv::Mat?&image,?int?div=64)?{??
  • ??????int?nr=?image.rows;?//?number?of?rows??
  • ??????int?nc=?image.cols?*?image.channels();?//?total?number?of?elements?per?line??
  • ??????for?(int?j=0;?j<nr;?j++)?{??
  • ??????????uchar*?data=?image.ptr<uchar>(j);??
  • ??????????for?(int?i=0;?i<nc;?i++)?{??
  • ??????????????????int?v=?*data;??
  • ??????????????????*data++=?v?-?v%div?+?div/2;??
  • ????????????}?//?end?of?row???????????????????
  • ??????}??
  • }??

  • 方法三:.ptr、指針運(yùn)算和位運(yùn)算

    由于進(jìn)行量化的單元div通常是2的整次方,因此所有的乘法和除法都可以用位運(yùn)算表示。

    [cpp]?view plaincopy
  • //?using?.ptr?and?*?++?and?bitwise??
  • void?colorReduce3(cv::Mat?&image,?int?div=64)?{??
  • ??????int?nr=?image.rows;?//?number?of?rows??
  • ??????int?nc=?image.cols?*?image.channels();?//?total?number?of?elements?per?line??
  • ??????int?n=?static_cast<int>(log(static_cast<double>(div))/log(2.0));??
  • ??????//?mask?used?to?round?the?pixel?value??
  • ??????uchar?mask=?0xFF<<n;?//?e.g.?for?div=16,?mask=?0xF0??
  • ??????for?(int?j=0;?j<nr;?j++)?{??
  • ??????????uchar*?data=?image.ptr<uchar>(j);??
  • ??????????for?(int?i=0;?i<nc;?i++)?{??
  • ????????????*data++=?*data&mask?+?div/2;??
  • ????????????}?//?end?of?row???????????????????
  • ??????}??
  • }??

  • 方法四:指針運(yùn)算

    方法四和方法三量化處理的方法相同,不同的是用指針運(yùn)算代替*++操作。

    [cpp]?view plaincopy
  • //?direct?pointer?arithmetic??
  • void?colorReduce4(cv::Mat?&image,?int?div=64)?{??
  • ??????int?nr=?image.rows;?//?number?of?rows??
  • ??????int?nc=?image.cols?*?image.channels();?//?total?number?of?elements?per?line??
  • ??????int?n=?static_cast<int>(log(static_cast<double>(div))/log(2.0));??
  • ??????int?step=?image.step;?//?effective?width??
  • ??????//?mask?used?to?round?the?pixel?value??
  • ??????uchar?mask=?0xFF<<n;?//?e.g.?for?div=16,?mask=?0xF0??
  • ??????//?get?the?pointer?to?the?image?buffer??
  • ??????uchar?*data=?image.data;??
  • ??????for?(int?j=0;?j<nr;?j++)?{??
  • ??????????for?(int?i=0;?i<nc;?i++)?{??
  • ????????????*(data+i)=?*data&mask?+?div/2;??
  • ????????????}?//?end?of?row???????????????????
  • ????????????data+=?step;??//?next?line??
  • ??????}??
  • }??

  • 方法五:.ptr、*++、位運(yùn)算以及image.cols * image.channels()

    這種方法就是沒(méi)有計(jì)算nc,基本是個(gè)充數(shù)的方法。

    [cpp]?view plaincopy
  • //?using?.ptr?and?*?++?and?bitwise?with?image.cols?*?image.channels()??
  • void?colorReduce5(cv::Mat?&image,?int?div=64)?{??
  • ??????int?nr=?image.rows;?//?number?of?rows??
  • ??????int?n=?static_cast<int>(log(static_cast<double>(div))/log(2.0));??
  • ??????//?mask?used?to?round?the?pixel?value??
  • ??????uchar?mask=?0xFF<<n;?//?e.g.?for?div=16,?mask=?0xF0??
  • ??????for?(int?j=0;?j<nr;?j++)?{??
  • ??????????uchar*?data=?image.ptr<uchar>(j);??
  • ??????????for?(int?i=0;?i<image.cols?*?image.channels();?i++)?{??
  • ????????????*data++=?*data&mask?+?div/2;??
  • ????????????}?//?end?of?row???????????????????
  • ??????}??
  • }??
  • ?

    方法六:連續(xù)圖像

    Mat提供了isContinuous()函數(shù)用來(lái)查看Mat在內(nèi)存中是不是連續(xù)存儲(chǔ),如果是則圖片被存儲(chǔ)在一行中。

    [cpp]?view plaincopy
  • //?using?.ptr?and?*?++?and?bitwise?(continuous)??
  • void?colorReduce6(cv::Mat?&image,?int?div=64)?{??
  • ??????int?nr=?image.rows;?//?number?of?rows??
  • ??????int?nc=?image.cols?*?image.channels();?//?total?number?of?elements?per?line??
  • ??????if?(image.isContinuous())??{??
  • ??????????//?then?no?padded?pixels??
  • ??????????nc=?nc*nr;???
  • ??????????nr=?1;??//?it?is?now?a?1D?array??
  • ???????}??
  • ??????int?n=?static_cast<int>(log(static_cast<double>(div))/log(2.0));??
  • ??????//?mask?used?to?round?the?pixel?value??
  • ??????uchar?mask=?0xFF<<n;?//?e.g.?for?div=16,?mask=?0xF0??
  • ??????for?(int?j=0;?j<nr;?j++)?{??
  • ??????????uchar*?data=?image.ptr<uchar>(j);??
  • ??????????for?(int?i=0;?i<nc;?i++)?{??
  • ????????????*data++=?*data&mask?+?div/2;??
  • ????????????}?//?end?of?row???????????????????
  • ??????}??
  • }??

  • 方法七:continuous+channels

    與方法六基本相同,也是充數(shù)的。

    [cpp]?view plaincopy
  • //?using?.ptr?and?*?++?and?bitwise?(continuous+channels)??
  • void?colorReduce7(cv::Mat?&image,?int?div=64)?{??
  • ??????int?nr=?image.rows;?//?number?of?rows??
  • ??????int?nc=?image.cols?;?//?number?of?columns??
  • ??????if?(image.isContinuous())??{??
  • ??????????//?then?no?padded?pixels??
  • ??????????nc=?nc*nr;???
  • ??????????nr=?1;??//?it?is?now?a?1D?array??
  • ???????}??
  • ??????int?n=?static_cast<int>(log(static_cast<double>(div))/log(2.0));??
  • ??????//?mask?used?to?round?the?pixel?value??
  • ??????uchar?mask=?0xFF<<n;?//?e.g.?for?div=16,?mask=?0xF0??
  • ??????for?(int?j=0;?j<nr;?j++)?{??
  • ??????????uchar*?data=?image.ptr<uchar>(j);??
  • ??????????for?(int?i=0;?i<nc;?i++)?{??
  • ????????????*data++=?*data&mask?+?div/2;??
  • ????????????*data++=?*data&mask?+?div/2;??
  • ????????????*data++=?*data&mask?+?div/2;??
  • ????????????}?//?end?of?row???????????????????
  • ??????}??
  • }??

  • 方法八:Mat _iterator

    真正有區(qū)別的方法來(lái)啦,用Mat提供的迭代器代替前面的[]操作符或指針,血統(tǒng)純正的官方方法~

    [cpp]?view plaincopy
  • //?using?Mat_?iterator???
  • void?colorReduce8(cv::Mat?&image,?int?div=64)?{??
  • ??????//?get?iterators??
  • ??????cv::Mat_<cv::Vec3b>::iterator?it=?image.begin<cv::Vec3b>();??
  • ??????cv::Mat_<cv::Vec3b>::iterator?itend=?image.end<cv::Vec3b>();??
  • ??????for?(?;?it!=?itend;?++it)?{??
  • ????????(*it)[0]=?(*it)[0]/div*div?+?div/2;??
  • ????????(*it)[1]=?(*it)[1]/div*div?+?div/2;??
  • ????????(*it)[2]=?(*it)[2]/div*div?+?div/2;??
  • ??????}??
  • }??
  • ?

    方法九:Mat_ iterator 和位運(yùn)算

    把方法八中的乘除法換成位運(yùn)算。

    [cpp]?view plaincopy
  • //?using?Mat_?iterator?and?bitwise??
  • void?colorReduce9(cv::Mat?&image,?int?div=64)?{??
  • ??????//?div?must?be?a?power?of?2??
  • ??????int?n=?static_cast<int>(log(static_cast<double>(div))/log(2.0));??
  • ??????//?mask?used?to?round?the?pixel?value??
  • ??????uchar?mask=?0xFF<<n;?//?e.g.?for?div=16,?mask=?0xF0??
  • ??????//?get?iterators??
  • ??????cv::Mat_<cv::Vec3b>::iterator?it=?image.begin<cv::Vec3b>();??
  • ??????cv::Mat_<cv::Vec3b>::iterator?itend=?image.end<cv::Vec3b>();??
  • ??????for?(?;?it!=?itend;?++it)?{??
  • ????????(*it)[0]=?(*it)[0]&mask?+?div/2;??
  • ????????(*it)[1]=?(*it)[1]&mask?+?div/2;??
  • ????????(*it)[2]=?(*it)[2]&mask?+?div/2;??
  • ??????}??
  • }??

  • 方法十:MatIterator_

    和方法八基本相同。

    [cpp]?view plaincopy
  • //?using?MatIterator_???
  • void?colorReduce10(cv::Mat?&image,?int?div=64)?{??
  • ??????cv::Mat_<cv::Vec3b>?cimage=?image;??
  • ??????cv::Mat_<cv::Vec3b>::iterator?it=cimage.begin();??
  • ??????cv::Mat_<cv::Vec3b>::iterator?itend=cimage.end();??
  • ??????for?(?;?it!=?itend;?it++)?{???
  • ????????(*it)[0]=?(*it)[0]/div*div?+?div/2;??
  • ????????(*it)[1]=?(*it)[1]/div*div?+?div/2;??
  • ????????(*it)[2]=?(*it)[2]/div*div?+?div/2;??
  • ??????}??
  • }??
  • ?

    方法十一:圖像坐標(biāo)

    [cpp]?view plaincopy
  • //?using?(j,i)??
  • void?colorReduce11(cv::Mat?&image,?int?div=64)?{??
  • ??????int?nr=?image.rows;?//?number?of?rows??
  • ??????int?nc=?image.cols;?//?number?of?columns??
  • ??????for?(int?j=0;?j<nr;?j++)?{??
  • ??????????for?(int?i=0;?i<nc;?i++)?{??
  • ??????????????????image.at<cv::Vec3b>(j,i)[0]=?????image.at<cv::Vec3b>(j,i)[0]/div*div?+?div/2;??
  • ??????????????????image.at<cv::Vec3b>(j,i)[1]=?????image.at<cv::Vec3b>(j,i)[1]/div*div?+?div/2;??
  • ??????????????????image.at<cv::Vec3b>(j,i)[2]=?????image.at<cv::Vec3b>(j,i)[2]/div*div?+?div/2;??
  • ????????????}?//?end?of?row???????????????????
  • ??????}??
  • }??

  • 方法十二:創(chuàng)建輸出圖像

    之前的方法都是直接修改原圖,方法十二新建了輸出圖像,主要用于后面的時(shí)間對(duì)比。

    [cpp]?view plaincopy
  • //?with?input/ouput?images??
  • void?colorReduce12(const?cv::Mat?&image,?//?input?image???
  • ?????????????????cv::Mat?&result,??????//?output?image??
  • ?????????????????int?div=64)?{??
  • ??????int?nr=?image.rows;?//?number?of?rows??
  • ??????int?nc=?image.cols?;?//?number?of?columns??
  • ??????//?allocate?output?image?if?necessary??
  • ??????result.create(image.rows,image.cols,image.type());??
  • ??????//?created?images?have?no?padded?pixels??
  • ??????nc=?nc*nr;???
  • ??????nr=?1;??//?it?is?now?a?1D?array??
  • ??????int?n=?static_cast<int>(log(static_cast<double>(div))/log(2.0));??
  • ??????//?mask?used?to?round?the?pixel?value??
  • ??????uchar?mask=?0xFF<<n;?//?e.g.?for?div=16,?mask=?0xF0??
  • ??????for?(int?j=0;?j<nr;?j++)?{??
  • ??????????uchar*?data=?result.ptr<uchar>(j);??
  • ??????????const?uchar*?idata=?image.ptr<uchar>(j);??
  • ??????????for?(int?i=0;?i<nc;?i++)?{??
  • ????????????*data++=?(*idata++)&mask?+?div/2;??
  • ????????????*data++=?(*idata++)&mask?+?div/2;??
  • ????????????*data++=?(*idata++)&mask?+?div/2;??
  • ??????????}?//?end?of?row???????????????????
  • ??????}??
  • }??

  • 方法十三:重載操作符

    Mat重載了+&等操作符,可以直接將兩個(gè)Scalar(B,G,R)數(shù)據(jù)進(jìn)行位運(yùn)算和數(shù)學(xué)運(yùn)算。

    [cpp]?view plaincopy
  • //?using?overloaded?operators??
  • void?colorReduce13(cv::Mat?&image,?int?div=64)?{??
  • ??????int?n=?static_cast<int>(log(static_cast<double>(div))/log(2.0));??
  • ??????//?mask?used?to?round?the?pixel?value??
  • ??????uchar?mask=?0xFF<<n;?//?e.g.?for?div=16,?mask=?0xF0??
  • ??????//?perform?color?reduction??
  • ??????image=(image&cv::Scalar(mask,mask,mask))+cv::Scalar(div/2,div/2,div/2);??
  • }??

  • 時(shí)間對(duì)比

    通過(guò)迭代二十次取平均時(shí)間,得到每種方法是運(yùn)算時(shí)間如下。

    可以看到,指針*++訪問(wèn)和位運(yùn)算是最快的方法;而不斷的計(jì)算image.cols*image.channles()花費(fèi)了大量重復(fù)的時(shí)間;另外迭代器訪問(wèn)雖然安全,但性能遠(yuǎn)低于指針運(yùn)算;通過(guò)圖像坐標(biāo)(j,i)訪問(wèn)時(shí)最慢的,使用重載操作符直接運(yùn)算效率最高。

    總結(jié)

    以上是生活随笔為你收集整理的访问Mat中每个像素的值的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。