2016-05-27 9 views
2

私は客観的なC/C++とopenCVでプログラムを構築しています。私はObjective Cではかなり熟練していますが、C++では初めてです。
私はカスタムRGB2HSVアルゴリズムを構築しています。私のアルゴリズムはopenCVライブラリcvtColor(in、out、CV_RGB2HSV)と少し異なります。
フォームMatlabをopencV/C++に変換しようとすると、後で処理する前に追加のフィルタリングが不要なので、きれいなHSV画像が得られます。以下のコード - Matlabコードは自明です。高度なrgb2hsv変換Matlabからピクセル値へのopnecv/C++へのアクセス

私はそれをC++/openCV関数に変換しようとしていますが、画像のピクセル値にアクセスしようと壁に当たっています。私はC++を初めて使っています。 私はMat構造にアクセスする方法をたくさん読んでいましたが、通常、 "\ 202 k g"のような数字のいずれか、またはゼロの場所で文字の束を取得します。 \ 202という乗算演算をしようとすると、結果は数学とは関係ありません。

ピクセル値に正しくアクセスするのを手伝ってください。また、現在のバージョンでは、一部の値が0-255の範囲外にあるため、ucharを使用しても機能しません。 アルゴリズムは私のものではありません。私はソースを指摘することすらできませんが、在庫RGB2HSVよりも明らかに優れた結果を出します。

また、以下のアルゴリズムは1ピクセルです。イメージの各ピクセルに適用する必要があります。最終バージョンでは{for {}}ループでラップする必要があります。

また、この方法をコミュニティと共有して、誰もがそのメリットを得て、プリフィルタリングを保存することができます。

私はC++/openCVに翻訳してください。できるだけベストプラクティスでスピードを賢明にする。または少なくともピクセル値に明確にアクセスする方法は、数学的方程式の範囲で実行可能です。前もって感謝します。 3チャンネル、8ビット精度の画像の画素の値にアクセスするには

function[H, S, V] = rgb2hsvPixel(R,G,B) 

% Algorithm: 

% In case of 8-bit and 16-bit images, `R`, `G`, and `B` are converted to the 
% floating-point format and scaled to fit the 0 to 1 range. 
% 
% V = max(R,G,B) 
% S =/(V - min(R,G,B))/V    if V != 0 
%  \ 0         otherwise 
%  /60*(G-B)/(V - min(R,G,B))  if V=R 
% H = | 120 + 60*(B-R)/(V - min(R,G,B)) if V=G 
%  \ 240 + 60*(R-G)/(V - min(R,G,B)) if V=B 
% 
% If `H<0` then `H=H+360`. On output `0<=V<=1`, `0<=S<=1`, `0<=H<=360`. 



     red = (double(R)-16)*255/224;     % \ 
     green = (double(G)-16)*255/224;    % }- R,G,B (0 <-> 255) -> (-18.2143 <-> 272.0759) 
     blue = (min(double(B)*2,240)-16)*255/224;  %/
     minV = min(red,min(green,blue)); 
     value = max(red,max(green,blue)); 

     delta = value - minV; 
     if(value~=0) 
      sat = (delta*255)/value;% s 
      if (delta ~= 0) 
       if(red == value) 
        hue = 60*(green - blue)/delta;  % between yellow & magenta 
       elseif(green == value) 
        hue = 120 + 60*(blue - red)/delta; % between cyan & yellow 
       else 
        hue = 240 + 60*(red - green)/delta; % between magenta & cyan 
       end 
       if(hue < 0) 
        hue = hue + 360; 
       end 
      else 
       hue = 0; 
       sat = 0; 
      end 
     else 
      % r = g = b = 0 
      sat = 0; 
      hue = 0; 
     end 
     H = max(min(floor(((hue*255)/360)),255),0); 
     S = max(min(floor(sat),255),0); 
     V = max(min(floor(value),255),0); 
    end 
+0

あなたは正確に尋ねていますか? C++のMatオブジェクトの1ピクセルの値にアクセスするには?または、RGBをHSVに変換するための完全な作業コードが必要ですか? – Sunreef

+0

少なくとも、ピクセルの実行可能な値に到達する方法。誰かがコミュニティに有益な機能を全面的に構築するのを助けることができれば。私は単純な数学的な論理でそれを構築することができますが、私はC++でもっとも効果的な方法ではないことを認識しています –

答えて

1

(タイプCV_8UC3)あなたはこのようにそれをしなければならない。

cv::Mat image; 
cv::Vec3b BGR = image.at<cv::Vec3b>(i,j); 

あなたが言うように、もし、8ビットの精度と範囲では不十分な場合は、浮動小数点32ビットの数値を格納するCV_32Fcv::Matを宣言できます。

cv::Mat image(height, width, CV_32FC3); 
//fill your image with data 
for(int i = 0; i < image.rows; i++) { 
    for(int j = 0; j < image.cols; j++) { 
     cv::Vec3f BGR = image.at<cv::Vec3f>(i,j) 
     //process your pixel 
     cv::Vec3f HSV; //your calculated HSV values 
     image.at<cv::Vec3f>(i,j) = HSV; 
    } 
} 

OpenCVはRGB値ではなく、BGR順にrgb値を格納することに注意してください。詳細については、OpenCV docsをご覧ください。

+1

私はそれが '' cv :: Mat image(height、width、CV_32FC3) cv ::マット画像(高さ、幅、CV_32F); '? – Catree

+0

@Catreeあなたが正しいです。私の悪い、私は注意を払っていませんでした。私はそれを修正します。 – Sunreef

+0

ピクセル値にアクセスする方法をテストしています: cout << "" <<固定; cv :: Vec3f BGR = image.at (x、y); cout << BGR << endl; cout << image.at (x、y)[0] << endl; cout << image.at (x、y)<< endl; cout << image.at (x、y)<< endl; [4087829327384284871262208.000000、0.000000、0.000000] Z [122、120、119] [28272、26989、:端末ウィンドウで は、同じ点は、ここで彼らはVec3b Vec3f Vec3sの用途に応じて全て異なる値を有しています26215] [15648626369888256.000000、1024100729431785472.000000] **何か不足していますか?** –

0

パフォーマンスに関して懸念があり、ピクセルインデックスがかなり快適な場合は、Mat ptrを直接使用できます。例えば

:前のコードが印刷する必要

cv::Mat img = cv::Mat::zeros(4, 8, CV_8UC3); 

    uchar *ptr_row_img; 
    int cpt = 0; 
    for(int i = 0; i < img.rows; i++) { 
    ptr_row_img = img.ptr<uchar>(i); 

    for(int j = 0; j < img.cols; j++) { 
     for(int c = 0; c < img.channels(); c++, cpt++, ++ptr_row_img) { 
     *ptr_row_img = cpt; 
     } 
    } 
    } 

    std::cout << "img=\n" << img << std::endl; 

IMG = [0、1、2、3、4、5、6、7、8、9、10 、11,12、 13,14,15,16,17,18,19,20,21,22,23; 24、25、26、 27,28,29,30,31,32,33,34,35,36,37,38,39,40,,41,42,43,44,45,46,47; 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68, 69,70,71; 72,73,74,75,76,77,78,79,80,81,82, 83,84,85,86,87,88,89,90,91,92,93,94,95

atアクセスは、ほとんどの場合のために十分とPTRのアクセスを使用するよりもミスをするためにはるかに読みやすい/にくくなるはずです。

参考文献:

+0

効率的なアクセスのために、私は最良のデータポインタがまだ 'Vec3b * imageData =(Vec3b *)image.data;に未処理のポインタを使用していると思います。 – Sunreef

0

enter image description here助けてくれてありがとうみんな。 あなたのヒントのおかげで私はカスタムrgb2hsv関数C++/openCVを構築しました。

それぞれ左上から、bgr-> gray-> edges、bgr-> HSV-> edges、bgr-> customHSV-> edgesの後ろにある それぞれの下には、ほぼ同じ明確な結果。フィルタの半径が大きければ大きいほど、複雑で時間のかかる計算になります。

画像処理の次のステップでより鮮明なエッジが生成されます。 これは、rg bチャンネルのパラメータをさらに実験することで調整できます。

赤=(赤色-16)* 1.1384; //255/244=1.1384 ここでは、より明確なVが 255/244となる数値が大きいほど、0から255の範囲を越えて延長される結果にも影響し、後でクリップされます。 この数字は黄金比だと思われますが、誰でも特定のニーズに合わせて調整することができます。

BGRをRGBに変換するこの機能を使用すると、生の画像の適切なチャンネルに色を直接接続することで回避できます。

おそらく少し不器用なパフォーマンスです。私の場合は、カラーバランスとヒストグラム調整の第一歩であり、速度はそれほど重要ではありません。

ビデオストリームを一定の処理で使用するには、速度の最適化が必要です。ポインタを使用してループの複雑さを軽減することが重要です。最適化はちょうど私のお茶のカップではありません。だから、誰かがそれをコミュニティのために最適化するのを助けたら、それは素晴らしいものになるでしょう。 ここで使用する準備ができました:

Mat bgr2hsvCustom (Mat& image) 
{ 
    //smallParam = 16; 
    for(int x = 0; x < image.rows; x++) 
    { 
     for(int y = 0; y<image.cols; y++) 
     { 
      //assigning vector to individual float BGR values 
      float blue = image.at<cv::Vec3b>(x,y)[0]; 
      float green = image.at<cv::Vec3b>(x,y)[1]; 
      float red = image.at<cv::Vec3b>(x,y)[2]; 

      float sat, hue, minValue, maxValue, delta; 

      float const ang0 = 0; // func min and max don't accept varaible and number 
      float const ang240 = 240; 
      float const ang255 = 255; 

      red = (red-16)*1.1384; //255/244 
      green = (green-16)*1.1384; 
      blue = (min(blue*2,ang240)-16)*1.1384; 
      minValue = min(red,min(green,blue)); 
      maxValue = max(red,max(green,blue)); 
      delta = maxValue - minValue; 

      if (maxValue != 0) 
      { 
       sat = (delta*255)/maxValue; 
       if (delta != 0) 
       { 
        if (red == maxValue){ 
         hue =  60*(green - blue)/delta; 
        } 
        else if(green == maxValue) { 
         hue = 120 + 60*(blue - red)/delta; 
        } 
        else{ 
         hue = 240 + 60*(red - green)/delta; 
        } 
        if(hue < 0){ 
         hue = hue + 360; 
        } 
       } 
       else{ 
        sat = 0; 
        hue = 0; 
       } 
      } 
      else{ 
       hue = 0; 
       sat = 0; 
      } 
      image.at<cv::Vec3b>(x,y)[0] = max(min(floor(maxValue),ang255),ang0);   //V 
      image.at<cv::Vec3b>(x,y)[1] = max(min(floor(sat),ang255),ang0);    //S 
      image.at<cv::Vec3b>(x,y)[2] = max(min(floor(((hue*255)/360)),ang255),ang0); //H 
     } 
    } 
    return image; 
} 
関連する問題