Untitled

 avatar
unknown
plain_text
14 days ago
11 kB
3
Indexable
#include <stdio.h>
using namespace std;


#include <iostream>
#include <cmath>

// OpenCV includes
#include <opencv2/opencv.hpp>

//#include "opencv2/core.hpp"
//#include "opencv2/highgui.hpp"
using namespace cv;

//utworzenie okna o nazwie name w punkcie (x,y) (lewy górny róg okna)
void CreateWindowAt(const char* name, int x, int y)
{ 
	namedWindow(name, WINDOW_AUTOSIZE);
	moveWindow(name, x, y);
}
// wyświetlenie obrazu img w oknie o nazwie name położonego w punkcie (x,y) (lewy górny róg okna)
void ShowImageAt(const char* name, Mat img, int x, int y)
{ 
	CreateWindowAt(name, x, y);
	imshow(name, img);
}
// wczytanie obrazu z pliku name do macierzy img
int read_image(const char* name, Mat* img)
{
	*img = imread(name);
	if (!(*img).data)
	{
		cout << "Error! Cannot read source file. Press ENTER.";
		waitKey(); // czekaj na naciśnięcie klawisza
		return(-1);
	}
	return 0;
}

int show_masked_image = 0;

Mat srcImage;			// obraz wejściowy
Mat greyImage;			// obraz po konwersji do obrazu w odcieniach szarości
Mat maskImage;
Mat secondImage;

//funkcja konwertująca obraz src na obraz dst w odcieniach szarości
void convertToGrey(Mat src, Mat dst)
{
	//pętla po wszystkich pikselach obrazu
	for (int x = 0; x < src.cols; x++)
		for (int y = 0; y < src.rows; y++)
		{
			//pobranie do zmiennej pixelColor wszystkich 3 składowych koloru piksela
			Vec3b pixelColor = src.at<Vec3b>(y, x);
			//konwersja na kolor szary; pixelColor[0] składowa B, pixelColor[1] składowa G, pixelColor[2] składowa R
			int gray = (int)(0.299f * pixelColor[2] + 0.587f * pixelColor[1] + 0.114f * pixelColor[0]);
			for (int i = 0; i < 3; i++) // for BGR elements
				pixelColor[i] = gray;
			//ustawienie obliczonej wartości piksela na obrazie wyjściowym
			dst.at<Vec3b>(y, x) = pixelColor;
		}
}

//fukcja zmieniająca kontrast i jasność obrazu src i umieszczająca wynik na obrazie dst
void BrightnessAndContrast(Mat src, Mat dst, float A, int B)
{
	//pętla po wszystkich pikselach obrazu
	for (int x = 0; x < src.cols; x++)
		for (int y = 0; y < src.rows; y++)
		{
			Vec3b pixelColor = src.at<Vec3b>(y, x);
			for (int i = 0; i < 3; i++) // for BGR elements
			{
				float pixelValue = A * pixelColor[i] + B;
				// Umieściłem tutaj odpowieni kod
				// Normalizacja
				if (pixelValue > 255)
					pixelValue = 255;
				else if (pixelValue < 0)
					pixelValue = 0;

				pixelColor[i] = (uchar)pixelValue;

			}
			dst.at<Vec3b>(y, x) = pixelColor;
		}
}
// wartość jasności (B)
int brightness_value = 100;
//wartość kontrastu (A)
int alpha_value = 200;			

// funkcja związana z suwakiem, wywoływana przy zmianie jego położenia
void BrightnessAndContrastCallBack(int pos, void* userdata)
{
	Mat* img = (Mat*)userdata;
	//wywołanie funkcji realizującej zmianę jasności i kontrastu BrightnessAndContrast
	BrightnessAndContrast(srcImage, *img, alpha_value / 100.0f, brightness_value - 200);
	imshow("Bright Image", *img);
}

//LUT - operacje potęgowe

uchar powerLUT[256];

void preparePowerLUT(float alpha)
{
	const int Jmax = 255;

	for (int i = 0; i < 256; i++)
	{
		float normalizedValue = (float)i / Jmax;
		float correctedValue = Jmax * pow(normalizedValue, alpha);
		
		if (correctedValue > Jmax)
			correctedValue = Jmax;
		else if (correctedValue < 0)
			correctedValue = 0;

		powerLUT[i] = (uchar)correctedValue;
		// Print values every 16 steps to keep the output manageable
		if (i % 16 == 0 || i == 255)
		{
			cout << i << "\t" << (int)powerLUT[i] << endl;
		}
	}
	cout << endl;
}

void applyPowerOperation(Mat src, Mat dst)
{
	for (int x = 0; x < src.cols; x++)
		for (int y = 0; y < src.rows; y++)
		{
			Vec3b pixelColor = src.at<Vec3b>(y, x);
			Vec3b newPixelColor;

			//pobranie do zmiennej pixelColor wszystkich 3 składowych koloru piksela
			for (int i = 0; i < 3; i++) // for BGR elements
			{
				newPixelColor[i] = powerLUT[pixelColor[i]];
			}
			dst.at<Vec3b>(y, x) = newPixelColor;
		}
}

// wartość alpha
int power_alpha_value = 100; // 1.0 (100/100)

// Funkcja callback dla suwaka operacji potęgowania
void PowerOperationCallBack(int pos, void* userdata)
{
	Mat* img = (Mat*)userdata;
	// Obliczenie wartości alpha z zakresu 0.1 - 3.0
	float alpha = power_alpha_value / 100.0f;

	// Przygotowanie tablicy LUT z aktualną wartością alpha
	preparePowerLUT(alpha);

	// Zastosowanie operacji potęgowania z użyciem LUT
	applyPowerOperation(srcImage, *img);

	// Aktualizacja wyświetlanego obrazu
	imshow("Power Operation", *img);
}

/// 3.1. Funkcja maskowania obrazu
void applyMasking(Mat srcImg, Mat maskImg, Mat dstImg)
{
	// Sprawdzenie czy wymiary obrazów są zgodne
	if (srcImg.cols != maskImg.cols || srcImg.rows != maskImg.rows)
	{
		cout << "Error: Source and mask image dimensions must match!" << endl;
		return;
	}

	for (int x = 0; x < srcImg.cols; x++)
		for (int y = 0; y < srcImg.rows; y++)
		{
			Vec3b srcPixel = srcImg.at<Vec3b>(y, x);
			Vec3b maskPixel = maskImg.at<Vec3b>(y, x);
			Vec3b resultPixel;

			for (int i = 0; i < 3; i++) // dla każdego kanału BGR
			{
				// Normalizacja wartości maski do zakresu 0-1
				float maskValue = maskPixel[i] / 255.0f;

				// Mnożenie piksela źródłowego przez wartość maski
				float resultValue = srcPixel[i] * maskValue;

				// Normalizacja wyniku
				if (resultValue > 255)
					resultValue = 255;
				else if (resultValue < 0)
					resultValue = 0;

				resultPixel[i] = (uchar)resultValue;
			}

			dstImg.at<Vec3b>(y, x) = resultPixel;
		}
}

// 3.2. Funkcja mieszania obrazów
void blendImages(Mat img1, Mat img2, Mat dstImg, float blendFactor)
{
	// Sprawdzenie czy wymiary obrazów są zgodne
	if (img1.cols != img2.cols || img1.rows != img2.rows)
	{
		cout << "Error: Both images must have the same dimensions for blending!" << endl;
		return;
	}

	for (int x = 0; x < img1.cols; x++)
		for (int y = 0; y < img1.rows; y++)
		{
			Vec3b pixel1 = img1.at<Vec3b>(y, x);
			Vec3b pixel2 = img2.at<Vec3b>(y, x);
			Vec3b blendedPixel;

			for (int i = 0; i < 3; i++) // dla każdego kanału BGR
			{
				// Wzór: Jwy(x,y) = a*J1(x,y) + (1-a)*J2(x,y)
				float blendedValue = blendFactor * pixel1[i] + (1.0f - blendFactor) * pixel2[i];

				// Normalizacja wyniku
				if (blendedValue > 255)
					blendedValue = 255;
				else if (blendedValue < 0)
					blendedValue = 0;

				blendedPixel[i] = (uchar)blendedValue;
			}

			dstImg.at<Vec3b>(y, x) = blendedPixel;
		}
}

// Wartość współczynnika mieszania
int blend_factor_value = 50; // domyślnie 0.5 (50/100)

// Funkcja callback dla suwaka mieszania obrazów
void BlendImagesCallBack(int pos, void* userdata)
{
	Mat* img = (Mat*)userdata;
	// Obliczenie wartości współczynnika mieszania z zakresu 0.0 - 1.0
	float blendFactor = blend_factor_value / 100.0f;

	cout << "Current blend factor: " << blendFactor << endl;

	// Zastosowanie mieszania obrazów
	blendImages(srcImage, maskImage, *img, blendFactor);

	// Aktualizacja wyświetlanego obrazu
	imshow("Blended Image", *img);
}

// Funkcja callback dla pokazania maskowanego obrazu
void ShowMaskedImageCallBack(int pos, void* userdata)
{
	Mat* img = (Mat*)userdata;

	if (show_masked_image == 1) // Apply the mask only if the slider is set to 1
	{
		applyMasking(srcImage, maskImage, *img);
	}
	else // Reset to the original image if the slider is set to 0
	{
		srcImage.copyTo(*img);
	}

	// Update the displayed image
	imshow("Masked Image", *img);
}

int main()
{
	// wczytanie obrazu do srcImage
	int r = read_image("Samples/zebra.jpg", &srcImage);
	if (r == -1) return(-1);
	ShowImageAt("Source image", srcImage, 0, 0);
	
	// Wczytanie drugiego obrazu (maska)
	r = read_image("Samples/maska.jpg", &maskImage);
	if (r == -1) {
		// Jeśli nie można wczytać maski, stwórz prostą maskę (ciemniejsza na brzegach, jaśniejsza w środku)
		maskImage = Mat(srcImage.size(), srcImage.type(), Scalar(0, 0, 0));

		int centerX = maskImage.cols / 2;
		int centerY = maskImage.rows / 2;
		int radius = std::min(centerX, centerY);

		for (int x = 0; x < maskImage.cols; x++) {
			for (int y = 0; y < maskImage.rows; y++) {
				// Obliczenie odległości od środka
				float distance = sqrt(pow(x - centerX, 2) + pow(y - centerY, 2));
				// Wartość maski maleje wraz z odległością od środka
				float value = std::max(0.0f, 1.0f - distance / radius);

				Vec3b pixelValue;
				pixelValue[0] = pixelValue[1] = pixelValue[2] = (uchar)(value * 255);
				maskImage.at<Vec3b>(y, x) = pixelValue;
			}
		}
	}
	ShowImageAt("Mask image", maskImage, 900, 0);

	// Grey image
	Mat greyImage;
	srcImage.copyTo(greyImage);
	convertToGrey(srcImage, greyImage);
	ShowImageAt("Grey image", greyImage, 450, 0);

	// zmiana jasności i kontrastu
	Mat brightImage;
	//zainicjowanie obrazu brightImage obrazem srcImage
	srcImage.copyTo(brightImage);


	CreateWindowAt("Bright Image", 0, 335);
	//tworzenie suwaka o nazwie "Contrast" związanego z oknem "Bright Image", alpha_value wartość całkowita, która będzie zmieniana przez trackbar, 700 maksymalna wartość na suwaku,  
	// BrightnessAndContrastCallBack funkcja wywoływana przy każdej zmianie pozycji suwaka, brightImage dane przekazywane do callback
	createTrackbar("Contrast", "Bright Image", &alpha_value, 700, BrightnessAndContrastCallBack, &brightImage);
	//analogicznie dodaj TrackBar dla jasności (brightness) 
	BrightnessAndContrastCallBack(0, &brightImage);
	//dodanie TrackBar dla jasności (brightness)
	createTrackbar("Brightness", "Bright Image", &brightness_value, 400, BrightnessAndContrastCallBack, &brightImage);

	// Operacja potęgowania z użyciem LUT
	Mat powerImage;
	srcImage.copyTo(powerImage);

	CreateWindowAt("Power Operation", 450, 335);
	// Utworzenie suwaka dla parametru alpha operacji potęgowania (zakres 0.1 - 3.0)
	createTrackbar("Alpha", "Power Operation", &power_alpha_value, 300, PowerOperationCallBack, &powerImage);

	// Wywołanie początkowe dla inicjalizacji obrazu
	PowerOperationCallBack(0, &powerImage);

	// 3.1 Operacja maskowania obrazu
	Mat maskedImage;
	srcImage.copyTo(maskedImage);

	CreateWindowAt("Masked Image", 0, 670);
	// Dodanie przycisku do pokazania maskowanego obrazu
	createTrackbar("Show", "Masked Image", &show_masked_image, 1, ShowMaskedImageCallBack, &maskedImage);
	// Inicjalne wywołanie maskowania
	ShowMaskedImageCallBack(0, &maskedImage);

	// 3.2 Operacja mieszania obrazów
	Mat blendedImage;
	srcImage.copyTo(blendedImage);

	CreateWindowAt("Blended Image", 450, 670);
	// Utworzenie suwaka dla współczynnika mieszania (zakres 0.0 - 1.0)
	createTrackbar("Blend Factor", "Blended Image", &blend_factor_value, 100, BlendImagesCallBack, &blendedImage);
	// Inicjalne wywołanie mieszania
	BlendImagesCallBack(0, &blendedImage);

	waitKey();


}

Editor is loading...
Leave a Comment