Kısa bir süre önce,  istediğimiz renkler dışındaki pikselleri MATLAB kullanarak nasıl siyah-beyaz yapabiliriz konusunda bir yazı yazmıştım. Yazıda erguvan rengini geçiren, diğer renkleri ise söndüren bir kod yazmıştık. Hatırlarsanız, yazıyı önemli bir uyarı ile bitirmiştik. Uyarıya uymayıp da denemek isteyen ama MATLAB'ı olmadığı için bu kodu çalıştıramayan çılgın maşuklar varsa üzülmesinler; okurlarımızdan A. Tahir İnce'nin önerisi üzerine bu yazıda aynı işlemi OpenCV'yi kullanarak yapacağız.

OpenCV diyorum ama aslında OpenCV2'yi, yani C++ arayüzünü kastediyorum. Zira, OpenCV'nin C fonksiyonlarından oluşan eski haliyle yazmayı hiç özlemiyorum. Neyse, Boğaziçi'nin simgesi dediğimiz erguvan resmimizi hatırlayalım:

Önceki yazıda ne yaptığımızı tekrar edelim. RGB uzayında çalışmak yerine, öncelikle resmi HSV uzayına attık. H (renk) kanalının değerlerine bakarak bir maske oluşturduk. H kanalının değerleri 0-360 derece arasında ise, erguvan rengine ait değerler 300-340 derece arasındaydı. Bunu da renklerin histogramını çizerek görmüştük. Daha sonra, oluşturduğumuz maskeyi kullanarak S (doygunluk) kanalındaki erguvan olmayan pikselleri sıfırlamış, yani bu pikselleri siyah beyaz yapmıştık. Ardından resmi özgün uzaya geri çevirmiştik. OpenCV'de de aynı işlemi yapacağız. Tek fark, S kanalının 0-360 derece arasında olması yerine 0-180 derece arasında olması. Dolayısıyla bizim istediğimiz sınırlar da öncekilerin yarısı olacak.

Lafı fazla uzatmadan kodu toptan vereyim, yorumlar da açıklamaları olsun:

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

void erguvan(cv::Mat& resim) {

    // Renk uzayını HSV'ye dönüştürelim.
    cv::cvtColor(resim, resim, CV_BGR2HSV);

    // Renkli resmi kanallara ayıralım: Hue (renk tonu),
    //  Saturation (doygunluk), Value (aydınlık).
    std::vector kanallar;
    cv::split(resim, kanallar);

    // Maskeyi oluşturalım
    //  Renk tonu (ilk kanal) 0-180 derecelik bir açı içinde olacak. 0-360 derece
    //  arasında düşünürken 300-340 arası erguvan rengiydi, dolayısıyla burada tam
    //  yarısı olacak. Resimler için aşırıyüklü (overloaded) mantıksal işlemleri
    //  kullanarak tek satırda bu işi halledebildik.
    cv::Mat maske = (kanallar[0] < 150) | (kanallar[0] > 170);

    // Maske, erguvan dışında renge sahip olan pikseller için doğru (true),
    //  diğerleri için yanlış (false) oldu. Maskenin doğru olduğu yerlerin
    //  doygunluğunu 0'a çektik, yani bu pikselleri siyah-beyaz yaptık.
    kanallar[1].setTo(cv::Scalar(0), maske);

    // Kanalları geri birleştirelim ve resmi özgün uzayına geri çevirelim.
    cv::merge(kanallar,resim);
    cv::cvtColor(resim, resim, CV_HSV2BGR);
}

void main() {

    // Resmi okuyalım.
    cv::Mat resim = cv::imread("erguvan.jpg");

    // Ekrana çizdirelim.
    cv::namedWindow("Resim");
    cv::imshow("Resim", resim);

    // Erguvan dışındaki renkleri söndürelim.
    erguvan(resim);

    // Güncel resmi ekrana çizelim.
    cv::namedWindow("Resim 2");
    cv::imshow("Resim 2", resim);

    // Sonucu kaydedelim.
    cv::imwrite("erguvan2.jpg", resim);

    cv::waitKey();
}

Kod biraz uzun gibi görünse de çoğu satır yorumdan ibaret. Ve sonuç yine şahane!