2017-12-04 2 views
0

Ich möchte eine negative Transformation für das Bild, das ein sehr einfaches Programm ist.Opencv nur die Teile des Bildes

Aber wenn ich das Programm ausführen. Ich möchte alle Pixel im Bild transformieren, aber nur 1/3 davon werden verarbeitet. Ich vergewissere mich nicht, wo es falsch ist. der ganze Code ich folgte dem Buch. Aber das Ergebnis ist anders.

Ich denke, dass etwas an den Spalten falsch ist, aber wenn ich den Wert von I.cols in negativeImage-Funktion mit dem tatsächlichen Wert des Bildes ändern. der Ausgang bleibt immer gleich. nur 1/3 Bildteile werden verarbeitet. Wenn ich dreimal die I.cols alle Pixel in der Iamge könnte verarbeitet werden.

vector<uchar> getNegativeLUT() { 
vector<uchar> LUT(256, 0); 
for (int i = 0; i < 256; ++i) 
    LUT[i] = (uchar)(255 - i); 
return LUT; 
} 

void negativeImage(Mat& I) { 
vector<uchar> LUT = getNegativeLUT(); 
for (int i = 0; i < I.rows; ++i) { 
    for (int j = 0; j < I.cols; ++j) { 
     I.at<uchar>(i, j) = LUT[I.at<uchar>(i, j)]; 
     //stack overflow 
    } 
    } 
} 

int main() { 
Mat image = imread("1.png"); 
Mat processed_image2 = image.clone(); 
negativeImage(processed_image2); 
printf("%d", image.cols); 

imshow("Input Image", image); 
imshow("Negative Image", processed_image2); 
waitKey(0); 

return 0; 
} 

Output Image

+0

try image.cloneTo (processed_image2) statt image.clone() –

+3

Sie arbeiten, als ob das Bild ein CV_8UC1 (Graustufen) war, aber es ist eigentlich CV_8UC3 (Farbe BGR). Also arbeite entweder an einem Graustufenbild: 'Mat image = imread (" 1.png ", cv :: IMREAD_GRAYSCALE);', oder korrigiere dein 'negativesImage' um auf 3 Kanälen zu arbeiten. Darf ich fragen, warum Sie nicht einfach: 'Mat processed_image = ~ image;'? – Miki

+0

Verwendung .at zuzugreifen 3-Kanal-8-Bit-Kanal-PE Pixel (wie Standard BGR Pixeltyp durch opencv verwendet, wenn nicht ausdrücklich anders gewählt) – Micka

Antwort

1

Sie benötigen richtigen Typen mit at<> Operator zu setzen. Ihr PNG-Bild muss in 8UC1 konvertiert werden, um dann den Typ uchar zu verwenden, um auf jedes Pixel zuzugreifen. Ich nehme an, Ihr Bild hat 3 Kanäle, so dass Sie nur über 1/3 des Bildes iterieren. Außerdem schlage ich vor, Sie verwenden ptr<> Operator in Zeilen Schleife und dann Zugriff auf Pixel als Array.

Mat M; 
cvtColor(I, M, CV_BGR2GRAY); 

// M is CV_8UC1 type 
for(int i = 0; i < M.rows; i++) 
{ 
    uchar* p = M.ptr<uchar>(i); 
    for(int j = 0; j < I.cols; j++) 
    { 
     p[j] = LUT[p[j]]; 
    } 
} 

EDIT: sollten Sie cv::LUT verwenden, anstatt es selbst zu tun.

cv::Mat lut(1, 256, CV_8UC1); 
for(int i = 0; i < 256; ++i) 
{ 
    lut.at<uchar>(0,i) = uchar(255-i); 
} 
cv::LUT(M, lut, result); 
+0

LUT ist eine schlechte Wahl, auch wenn Sie die OpenCV-Implementierung wiederverwenden, anstatt das Rad neu zu erfinden. Ein Nachschlagen für jedes Pixel wird niemals so gut funktionieren wie eine einfache arithmetische oder logische Operation und wird definitiv nicht so gut vektorisieren. Ganz zu schweigen davon, dass es wirklich verschleiert, was der Algorithmus wirklich macht. –

+0

Danke für Ihre Hilfe. Ich habe das Problem mit deiner Hilfe herausgefunden. :) –

Verwandte Themen