IntensityImage * ImageFactory::newIntensityImage(const IntensityImage &other) {
	IntensityImage * image = ImageFactory::newIntensityImage(other.getWidth(), other.getHeight());
	int size = other.getHeight() * other.getWidth();
	for (int i = 0; i < size; i++) {
		image->setPixel(i, other.getPixel(i));
	}
	return image;
}
IntensityImageStudent::IntensityImageStudent(const IntensityImage &other) : IntensityImage(other.getWidth(), other.getHeight()), pixelMap(nullptr) {
	const int SIZE = other.getSize();
	if(SIZE > 0) {
		pixelMap = new Intensity[SIZE];
		for(int i = 0; i < SIZE; i++) {
			pixelMap[i] = other.getPixel(i);
		}
	}
}
int StudentLocalization::getTopOfHead(const IntensityImage &image){
	for (int y = 0; y < image.getHeight(); y++){
		for (int x = 0; x < image.getWidth(); x++) {
			if (image.getPixel(x, y) == 0){
				return y;
			}
		}
	}
	return -1;
}
void IntensityImageStudent::set(const IntensityImage &other) {
	const int	SIZE = other.getSize();
	IntensityImage::set(other.getWidth(), other.getHeight());

	if (SIZE > 0) {
		delete[] pixelMap;
		pixelMap = new Intensity[SIZE];
		for (int i = 0; i < SIZE; i++) {
			pixelMap[i] = other.getPixel(i);
		}
	}
}
void HereBeDragons::HerLoveForWhoseDearLoveIRiseAndFall(const IntensityImage &src, cv::Mat &dst) {
	int w = src.getWidth();
	int h = src.getHeight();

	dst.create(h, w, CV_8UC1);

	for (int x = 0; x < dst.cols; x++) {
		for (int y = 0; y < dst.rows; y++) {
			dst.at<uchar>(y, x) = src.getPixel(x, y);
		}
	}
}
bool StudentLocalization::stepFindHead(const IntensityImage &image, FeatureMap &features) const {
	int yTop = getTopOfHead(image);
	int alpha = 13;
	int* histogram;
	int left, right;
	int diffFirstLast = -1, maxDiffFirstLast = -1;
	int ySides = -1;
	//number of slices the image will be 'cut' into for the histograms
	int count = ((image.getHeight() - yTop - 1) / alpha) + 1;

	for (int i = 0; i < count; i++) {
		//get histogram of current slice
		histogram = getHistogramX(image, alpha, yTop + i * alpha);
		findSidesInHistogram(histogram, image.getWidth(), &left, &right);
		//if no two sides have been found continue to the next slice
		if (left == -1 || right == -1) {
			continue;
		}

		//find the first peak gap between the left and right side to detect the position of the ears
		diffFirstLast = right - left;
		if (diffFirstLast > maxDiffFirstLast) {
			maxDiffFirstLast = diffFirstLast;
		}
		else {
			//if the gap is lower than the max, a peak has been found
			//and the y position of the ears will be set to the middle of the slice 
			//where the peak is detected
			ySides = yTop + (i + 1)  * alpha;
			break;
		}
	}
	//if no peak is detected return false
	if (ySides == -1) {
		return false;
	}

	//set the results in the feature map
	Point2D<double> * pointLeftSideHead = new Point2D<double>(left, ySides);
	Feature * leftSideHead = new Feature(Feature::FEATURE_HEAD_LEFT_SIDE, *pointLeftSideHead);
	features.putFeature(*leftSideHead);

	Point2D<double> * pointRightSideHead = new Point2D<double>(right, ySides);
	Feature * rightSideHead = new Feature(Feature::FEATURE_HEAD_RIGHT_SIDE, *pointRightSideHead);
	features.putFeature(*rightSideHead);

	Point2D<double> * pointTopOfHead = new Point2D<double>((left + right) / 2, yTop);
	Feature * topOfHead = new Feature(Feature::FEATURE_HEAD_TOP, *pointTopOfHead);
	features.putFeature(*topOfHead);
	
	return true;
}
void LuminosityAlgorithm::doAlgorithm(const RGBImage& input, IntensityImage& output)
{
	// Check image size
	if (input.getWidth() != output.getWidth() || input.getHeight() != output.getHeight()) {
		output.set(input.getWidth(), input.getHeight());
	}

	// Lunimosity Algorithm defined as
	// Gray = (Red * 0.2126 + Green * 0.7152 + Blue * 0.0722)
	for (int i = 0; i < input.getWidth()*input.getHeight(); i++) {
		RGB pixel = input.getPixel(i);
		output.setPixel(i, pixel.r * 0.2126 + pixel.g * 0.7152 + pixel.b * 0.0722);
	}
}
예제 #8
0
void Test::RunCannyTest(const RGBImage* in) {
	Gaussian smoother;
	Sobel sobel;
	Canny canny;
	StudentPreProcessing converter;

	double sigma = 1.6;
	int kernelSize = 5;

	// Convert RGB to Intensity
	IntensityImage* grey = ImageFactory::newIntensityImage(in->getWidth(), in->getHeight());
	grey = converter.stepToIntensityImage(*in);

	BaseTimer timer;
	int total = 0;
	for (int i = 0; i < 10; ++i) {
		timer.start();

		/* Start of Canny */

		// 1. Smooth Intensity with Gaussian
		IntensityImage* gaussian = ImageFactory::newIntensityImage(in->getWidth() - kernelSize, in->getHeight() - kernelSize);
		smoother.smoothImage(grey, gaussian, sigma, kernelSize);

		// 2. Find edges with Sobel (convolve X and Y separately for Canny)
		int sobelKernelSize = 3;
		IntensityImage* sobelX = ImageFactory::newIntensityImage(gaussian->getWidth() - sobelKernelSize, gaussian->getHeight() - sobelKernelSize);
		IntensityImage* sobelY = ImageFactory::newIntensityImage(gaussian->getWidth() - sobelKernelSize, gaussian->getHeight() - sobelKernelSize);
		sobel.filterXY(gaussian, sobelX, sobelY);

		// 3. Apply non-maximum suppresion
		IntensityImage* nonMaxSuppression = ImageFactory::newIntensityImage(sobelX->getWidth(), sobelX->getHeight());
		canny.nonMaximumSurpression(sobelX, sobelY, nonMaxSuppression);

		// 4. Apply hysteresis threshold
		IntensityImage* hysteresisThreshold = ImageFactory::newIntensityImage(sobelX->getWidth(), sobelX->getHeight());
		canny.threshold(nonMaxSuppression, hysteresisThreshold, 60, 70);

		timer.stop();
		std::cout << timer.elapsedMilliSeconds() << " ms" << std::endl;
		total += timer.elapsedMilliSeconds();
		timer.reset();

		if (i == 9)
			ImageIO::saveIntensityImage(*hysteresisThreshold, ImageIO::getDebugFileName("Canny.png"));
	}
	std::cout << "Average time per Canny edge detection: " << (total / 10) << " ms" << std::endl;
	std::cout << "Press the X in the console window to exit program" << std::endl;
}
IntensityImageStudent GaussianFilter::applyFilter(const IntensityImage &image)
{
	IntensityImageStudent filteredImage = IntensityImageStudent(image.getWidth() - 2 * radius, image.getHeight() - 2 * radius);
	
	for (int y = 0; y < filteredImage.getHeight(); y++){
		for (int x = 0; x < filteredImage.getWidth(); x++){
			double filteredIntensity = 0.0;
			for (unsigned int i = 0; i < gaussKernel.size(); i++){
				filteredIntensity += gaussKernel[i] * image.getPixel(x + (i % (2 * radius + 1)), y + i / (2 * radius + 1));
			}
			filteredImage.setPixel(x, y, static_cast<Intensity>(filteredIntensity));
		}
	}
	return filteredImage;
}
void HereBeDragons::NoWantOfConscienceHoldItThatICall(const cv::Mat &source, IntensityImage &dst) {
	int type = source.type();
	if (type != CV_8UC1) {
//		throw std::exception("OpenCV Mat source image not of type CV_8UC1!");
		throw std::exception{};
	}

	dst.set(source.cols, source.rows);

	for (int x = 0; x < source.cols; x++) {
		for (int y = 0; y < source.rows; y++) {
			dst.setPixel(x, y, source.at<uchar>(y, x));
		}
	}
}
예제 #11
0
bool StudentLocalization::stepFindChinContours(const IntensityImage &image, FeatureMap &features) const {
	
	const Feature & mouthCenter = features.getFeature(Feature::FEATURE_MOUTH_CENTER);
	const Feature & chin = features.getFeature(Feature::FEATURE_CHIN);
	Feature & chinContour = features.getFeature(Feature::FEATURE_CHIN_CONTOUR);

	// The mouth could interfere with the localization of the chin contours.
	// Therefore use an offset based on which mouthcorner is the furthest away.
	// This however could still prove troublesome, so add a slight margin; 
	// represented by the 'magic' number. 
	const double radius = chin.getY() - mouthCenter.getY();


	const double smallestOffsetRadiusFactor = 0.75;
	const double biggestOffsetRadiusFactor = 2;
	//

	// 180° matches half a circle.
	// 0° points to the east in goniometrics, where increasing angles are counter-clockwise.
	// Since the chin is usually on the bottompart of the image, the points either need to be
	// found clockwise (-180), or start looking at an offset.
	// 
	const int halfCircle = 180;
	const int angleStepSize = 10;
	// roughly 19 points need to be found.
	// 0 through 18 does just that.
	for (int i = 0; i <= halfCircle / angleStepSize; ++i)
	{
		// Determine the angle of the line among which we try to look for a point on the chin's contour.
		int angle = halfCircle + i * angleStepSize;
		
		// The size of a step in both the horizontal and verticical direction along the line with the current angle.
		double xDir = std::cos(angle * M_PI / 180.0);
		double yDir = -std::sin(angle * M_PI / 180.0);
		
		// Normalized size of a step that is made alongside the current angle.
		const double increment = 1;

		// Make multiple steps alongside the current angle within bounds where it is likely a contour for the chin.
		for (double distance = radius * smallestOffsetRadiusFactor; distance < radius * biggestOffsetRadiusFactor; distance += increment)
		{
			// Determine the location to check for a contour of the chin.
			double xCheck = mouthCenter.getX() + (xDir * distance);
			double yCheck = mouthCenter.getY() + (yDir * distance);
			// Image should be thresholded grayscale, where the pixels are eiher 0 or 255; check in the middle of it.
			const unsigned char treshhold = 128;
			if (image.getPixel(xCheck, yCheck) <= treshhold)
			{
				chinContour.addPoint(Point2D<double>(xCheck, yCheck));
				std::cout << "Found contour at: " << xCheck << "; " << yCheck << "\n";
				break;
			}
		}
	}

	return (chinContour.getPoints().size() > 0);
}
SonnetXVIII HereBeDragons::YetWhoKnowsNotConscienceIsBornOfLove(const IntensityImage &Yet, const int Who, const int Knows, const int Not, const int Conscience){
	SonnetXVIII Is(Conscience);
	int Born = 0;
	for (int y = Knows; y < (Knows + Conscience); y++){
		for (int x = Who; x < (Who + Not); x++){
			if (Yet.getPixel(x, y) == 0){
				Is[Born]++;
			}
		}
		Born++;
	}
	return Is;
}
SonnetXVIII HereBeDragons::LoveIsTooYoungToKnowWhatConscienceIs(const IntensityImage &Love, const int Is, const int Too, const int Young, const int To){
	SonnetXVIII Know(Young);
	int What = 0;
	for (int x = Is; x < (Is + Young); x++){
		for (int y = Too; y < (Too + To); y++){
			if (Love.getPixel(x, y) == 0){
				Know[What]++;
			}
		}
		What++;
	}
	return Know;
}
bool StudentLocalization::stepFindChinContours(const IntensityImage &image, FeatureMap &features) const {

	//Get the position of the mouth
	Feature Mouth = features.getFeature(Feature::FEATURE_MOUTH_TOP);
	Point2D<double> MouthPosition;
	
	//Initialise the chin feature
	std::vector<Point2D<double>> ChinPositions;
	Feature Chin = Feature(Feature::FEATURE_CHIN);
	Feature ChinContour = Feature(Feature::FEATURE_CHIN_CONTOUR);
	int y = 0;
	int m = 0;
	
	//Draw a half circle starting from the center of the mouth
	for (int j = HALF_CIRCLE; j > 0; j -= DEGREE_STEP){
		
		//reset the position of the mouth
		MouthPosition.set(Mouth.getX(), Mouth.getY());
		MouthPosition.set(drawLine(j, START_POSITION, MouthPosition));
	
		m = m + 1;

		
		for (int i = 0; i < MEASURE_RANGE; i++){

			MouthPosition.set(drawLine(j, MEASURE_STEP, MouthPosition));
			Intensity pixel = image.getPixel(MouthPosition.getX(), MouthPosition.getY());

			// If the intensity of the current pixel is lower than 2 (which means it is black)
			if (pixel < 2){ 
				
				// If the current angle is within the bounds of the half circle
				if (j < RIGHT_HALF && j > LEFT_HALF){
					ChinContour.addPoint(drawLine(j, 2, MouthPosition));
				}
				else{
					//Draw a point on the mouth position, to indicate the detection failed.
					ChinContour.addPoint(MouthPosition);
				}
				break;
			}
		}	
	}	
	features.putFeature(ChinContour);
	return true;
}
bool StudentLocalization::stepFindHead(const IntensityImage &image, FeatureMap &features) const {
	Histogram AxisY(image, 50, 50, 0, 0, Axis::y);
	
	//determine top of the head

	int topHead = -1;

	for (int i = 0; i < AxisY.getSize(); ++i) {
		if (AxisY.getValue(i) > 2) {
			topHead = i;
			break;
		}
	}
	if (topHead == -1) {
		return false;
	}
	
	//determine sides

	int lastLeftX = -1;
	int lastRightX = -1;
	for (int y = topHead; y < image.getHeight(); y += 20) {
		Histogram layerX(image, 0, 0, y, (image.getHeight() - y - 20), Axis::x);
		
		//determine leftside of the head
		int leftX = -1;
		for (int i = 0; i < layerX.getSize(); ++i) {
			if (layerX.getValue(i) > 2) {
				leftX = i;
				break;
			}
		}

		//determine rightside of the head
		int rightX = -1;
		for (int i = layerX.getSize() - 1; i >= 0 ; --i) {
			if (layerX.getValue(i) > 2) {
				rightX = i;
				break;
			}
		}
		
		// if not both sides are found skip the rest of the loop
		if (leftX == -1 || rightX == -1) {
			continue;
		}

		int currentHeadWidth = rightX - leftX;
		int lastHeadWidth = lastRightX - lastLeftX;

		if (currentHeadWidth < lastHeadWidth) {
			Feature * headUpperBound = new Feature(Feature::FEATURE_HEAD_TOP, Point2D<double>(lastRightX - (currentHeadWidth / 2), topHead));
			Feature * headLeftBound = new Feature(Feature::FEATURE_HEAD_LEFT_SIDE, Point2D<double>(lastLeftX, y));
			Feature * headRightBound = new Feature(Feature::FEATURE_HEAD_RIGHT_SIDE, Point2D<double>(lastRightX, y));

			features.putFeature(*headUpperBound);
			features.putFeature(*headLeftBound);
			features.putFeature(*headRightBound);
					
			return true;
		}

		lastLeftX = leftX;
		lastRightX = rightX;
	}
	
	return false;
}
예제 #16
0
void drawFeatureDebugImage(IntensityImage &image, FeatureMap &features) {
	RGB colorRed(244, 67, 54);
	RGBImage * debug = ImageFactory::newRGBImage(image.getWidth(), image.getHeight());
	ImageIO::intensityToRGB(image, *debug);

	//Nose
	Point2D<double> noseLeft = features.getFeature(Feature::FEATURE_NOSE_END_LEFT)[0];
	Point2D<double> noseRight = features.getFeature(Feature::FEATURE_NOSE_END_RIGHT)[0];
	Point2D<double> nostrilLeft = features.getFeature(Feature::FEATURE_NOSTRIL_LEFT)[0];
	Point2D<double> nostrilRight = features.getFeature(Feature::FEATURE_NOSTRIL_RIGHT)[0];
	Point2D<double> noseBottom = features.getFeature(Feature::FEATURE_NOSE_BOTTOM)[0];


	//These (weird) methods can be used to draw debug points
	HereBeDragons::TriumphInLoveFleshStaysNoFatherReason(*debug, noseLeft, colorRed);
	HereBeDragons::TriumphInLoveFleshStaysNoFatherReason(*debug, noseRight, colorRed);
	HereBeDragons::TriumphInLoveFleshStaysNoFatherReason(*debug, nostrilLeft, colorRed);
	HereBeDragons::TriumphInLoveFleshStaysNoFatherReason(*debug, nostrilRight, colorRed);
	HereBeDragons::TriumphInLoveFleshStaysNoFatherReason(*debug, noseBottom, colorRed);

	//Chin
	std::vector<Point2D<double>> points = features.getFeature(Feature::FEATURE_CHIN_CONTOUR).getPoints();
	for (size_t i = 0; i < points.size(); i++) {
		HereBeDragons::TriumphInLoveFleshStaysNoFatherReason(*debug, points[i], colorRed);
	}

	//Eye
	Feature leftEye = features.getFeature(Feature::FEATURE_EYE_LEFT_RECT);
	Feature rightEye = features.getFeature(Feature::FEATURE_EYE_RIGHT_RECT);


	//These (weird) methods can be used to draw debug rects
	HereBeDragons::AsHisTriumphantPrizeProudOfThisPride(*debug, leftEye[0], leftEye[1], colorRed);
	HereBeDragons::AsHisTriumphantPrizeProudOfThisPride(*debug, rightEye[0], rightEye[1], colorRed);


	//Head
	Feature headTop = features.getFeature(Feature::FEATURE_HEAD_TOP);
	Feature headLeftNoseMiddle = features.getFeature(Feature::FEATURE_HEAD_LEFT_NOSE_MIDDLE);
	Feature headLeftNoseBottom = features.getFeature(Feature::FEATURE_HEAD_LEFT_NOSE_BOTTOM);
	Feature headRightNoseMiddle = features.getFeature(Feature::FEATURE_HEAD_RIGHT_NOSE_MIDDLE);
	Feature headRightNoseBottom = features.getFeature(Feature::FEATURE_HEAD_RIGHT_NOSE_BOTTOM);
	HereBeDragons::TriumphInLoveFleshStaysNoFatherReason(*debug, headTop[0], colorRed);
	HereBeDragons::TriumphInLoveFleshStaysNoFatherReason(*debug, headLeftNoseMiddle[0], colorRed);
	HereBeDragons::TriumphInLoveFleshStaysNoFatherReason(*debug, headLeftNoseBottom[0], colorRed);
	HereBeDragons::TriumphInLoveFleshStaysNoFatherReason(*debug, headRightNoseMiddle[0], colorRed);
	HereBeDragons::TriumphInLoveFleshStaysNoFatherReason(*debug, headRightNoseBottom[0], colorRed);

	//Mouth
	Point2D<double> mouthTop = features.getFeature(Feature::FEATURE_MOUTH_TOP)[0];
	Point2D<double> mouthBottom = features.getFeature(Feature::FEATURE_MOUTH_BOTTOM)[0];
	Point2D<double> mouthLeft = features.getFeature(Feature::FEATURE_MOUTH_CORNER_LEFT)[0];
	Point2D<double> mouthRight = features.getFeature(Feature::FEATURE_MOUTH_CORNER_RIGHT)[0];

	//This (weird) method can be used to draw a debug line
	HereBeDragons::ButRisingAtThyNameDothPointOutThee(*debug, mouthLeft, mouthRight, colorRed);

	HereBeDragons::TriumphInLoveFleshStaysNoFatherReason(*debug, mouthTop, colorRed);
	HereBeDragons::TriumphInLoveFleshStaysNoFatherReason(*debug, mouthBottom, colorRed);
	HereBeDragons::TriumphInLoveFleshStaysNoFatherReason(*debug, mouthLeft, colorRed);
	HereBeDragons::TriumphInLoveFleshStaysNoFatherReason(*debug, mouthRight, colorRed);

	ImageIO::saveRGBImage(*debug, ImageIO::getDebugFileName("feature-points-debug.png"));
	delete debug;
}
예제 #17
0
bool StudentLocalization::stepFindChinContours(const IntensityImage &image, FeatureMap &features) const {
	// Maak een basetimer object om de tijd bij te houden dat de implementatie nodig heeft.
	BaseTimer basetimer;
	// Start de basetimer.
	basetimer.start();
	// test getal 
	int startStep = 15; 
	bool first = true;
	// Sla het middenpunt van de mond op.
	Point2D<double> MouthCenterPoint = features.getFeature(Feature::FEATURE_MOUTH_CENTER).getPoints()[0];
	// Sla het kin punt op.
	Point2D<double> ChinPoint = features.getFeature(Feature::FEATURE_CHIN).getPoints()[0];
	int range = MouthCenterPoint.getY() - ChinPoint.getY();
	// Object om kincountoer punten in op te slaan.
	Feature output = Feature(Feature::FEATURE_CHIN_CONTOUR);
	int degrees;
	int steps = 15;
	int lastdif;
	double correction = -1;
	int lastSteps = 0;
	int vorigeX = 0;
	// Bereken 20 punten van de kin.
	for (int i = 0; i < 19; i++)
	{
		bool ireg = false;
		if (i>9)
		{ 
			correction = 1; 
		}
		else if (i < 9)
		{ 
			correction =0;
		}
		// Sla middelpunt mond x op.
		int checkX = MouthCenterPoint.getX();
		// Sla middelpunt mond y op.
		int checkY = MouthCenterPoint.getY();
		double gradenInRad = (-90+(i * 10)) *(PI/180);
		steps = startStep;
		Point2D<double> gevondenPunt;
		// Middelste punt van de kin is als het goed is bekend. Dit is punt nummer 9 dus zal worden overgeslagen.
		if (i != 9) 
		{
			while (true)
			{
				if (!first&&steps > startStep + 10)
				{ 
					lastdif / i;
					ireg = true;
					gevondenPunt.set(MouthCenterPoint.getX() + ((lastSteps + correction)* std::sin(gradenInRad)), MouthCenterPoint.getY() + ((lastSteps + correction) * std::cos(gradenInRad)));
					steps = lastSteps + correction;
					break;
				}
				checkX = MouthCenterPoint.getX()+ (steps * std::sin(gradenInRad));
				checkY = MouthCenterPoint.getY()+(steps * std::cos(gradenInRad));
				Intensity pixel = image.getPixel(std::round(checkX), std::round(checkY));
				if (int(pixel) == 0)
				{
					if (checkX - vorigeX <2)
					{
						lastdif / i;
						ireg = true;
						gevondenPunt.set(MouthCenterPoint.getX() + ((lastSteps + correction)* std::sin(gradenInRad)), MouthCenterPoint.getY() + ((lastSteps + correction) * std::cos(gradenInRad)));
						steps = lastSteps + correction;
						break;
					}
					ireg=false;
					gevondenPunt.set(checkX, checkY); break; 
				}
				steps++;
			}
			vorigeX = checkX;
			std::cout << gevondenPunt <<"\n";
			startStep = steps - 5;
			output.addPoint(Point2D<double>(gevondenPunt.x,gevondenPunt.y));
			first=false;
			if (ireg)
			{
				startStep = steps-5;
				lastSteps = steps;
			}
			else
			{
				lastdif = lastSteps - steps;
				lastSteps = steps;
			}
		}
		else
		{ 
			output.addPoint(ChinPoint); 
		}
	}
	features.putFeature(output);
	basetimer.stop();
	std::ofstream myfile;
	myfile.open("tijd.txt", std::ofstream::ate);
	myfile << "Chincontours convert tijd in s: " << basetimer.elapsedSeconds() << " tijd ms:" << basetimer.elapsedMilliSeconds() << " tijd us" << basetimer.elapsedMicroSeconds();
	myfile.close();
	return true;
}