OpenCV—python 图像积分图

积分图原理

关于积分图原理:https://www.cnblogs.com/magic-428/p/9149868.html

第一个提出 Haar 特征快速计算方法的是 CVPR2001上 的那篇经典论文 [《Rapid object detection using a boosted cascade of simple features》] (http://www.cs.utexas.edu/~grauman/courses/spring2007/395T/papers/viola_cvpr2001.pdf), Viola 提出了一种利用积分图(integral image)快速计算 Haar 特征的方法, 这个方法使得图像的局部矩形求和运算的复杂度从 O(MN) 下降到了 O(4)

关于C++演示:https://blog.csdn.net/jia20003/article/details/7201069
详情信息:http://www.cnblogs.com/Imageshop/p/6219990.html


void GetGrayIntegralImage(unsigned char *Src, int *Integral, int Width, int Height, int Stride)
{

	memset(Integral, 0, (Width + 1) * sizeof(int));					//	第一行都为0
	for (int Y = 0; Y < Height; Y++)
	{
		unsigned char *LinePS = Src + Y * Stride;
		int *LinePL = Integral + Y * (Width + 1) + 1;				//	上一行位置			
		int *LinePD = Integral + (Y + 1) * (Width + 1) + 1;			//	当前位置,注意每行的第一列的值都为0
		LinePD[-1] = 0;												//	第一列的值为0
		for (int X = 0, Sum = 0; X < Width; X++)
		{
			Sum += LinePS[X];										//	行方向累加
			LinePD[X] = LinePL[X] + Sum;							//	更新积分图
		}
	}
}

void GetRGBIntegralImage(unsigned char *Src, int *Integral, int Width, int Height, int Stride)
{
	const int Channel = 3;
	memset(Integral, 0, (Width + 1) * Channel * sizeof(int));
	for (int Y = 0; Y < Height; Y++)
	{
		unsigned char *LinePS = Src + Y * Stride;
		int *LinePL = Integral + Y * (Width + 1) * Channel + Channel;
		int *LinePD = Integral + (Y + 1) * (Width + 1) * Channel + Channel;
		LinePD[-3] = 0; LinePD[-2] = 0; LinePD[-1] = 0;
		for (int X = 0, SumB = 0, SumG = 0, SumR = 0; X < Width; X++)
		{
			SumB += LinePS[0];
			SumG += LinePS[1];
			SumR += LinePS[2];
			LinePD[0] = LinePL[0] + SumB;
			LinePD[1] = LinePL[1] + SumG;
			LinePD[2] = LinePL[2] + SumR;
			LinePS += Channel;
			LinePL += Channel;
			LinePD += Channel;
		}
	}
}



void BoxBlur(unsigned char *Src, unsigned char *Dest, int Width, int Height, int Stride, int Radius)
{
	int Channel = Stride / Width;
	int *Integral = (int *)malloc((Width + 1) * (Height + 1) * Channel * sizeof(int));
	if (Channel == 1)
	{
		GetGrayIntegralImage(Src, Integral, Width, Height, Stride);
		#pragma omp parallel for
		for (int Y = 0; Y < Height; Y++)
		{
			int Y1 = max(Y - Radius, 0);
			int Y2 = min(Y + Radius + 1, Height);
			//	int Y1 = Y - Radius;
			//	int Y2 = Y + Radius + 1;
			//	if (Y1 < 0) Y1 = 0;
			//	if (Y2 > Height) Y2 = Height;
			int *LineP1 = Integral + Y1 * (Width + 1);
			int *LineP2 = Integral + Y2 * (Width + 1);
			unsigned char *LinePD = Dest + Y * Stride;
			for (int X = 0; X < Width; X++)
			{
				int X1 = max(X - Radius, 0);
				int X2 = min(X + Radius + 1, Width);
				//	int X1 = X - Radius;
				//	if (X1 < 0) X1 = 0;
				//	int X2 = X + Radius + 1;
				//	if (X2 > Width) X2 = Width;
				int Sum = LineP2[X2] - LineP1[X2] - LineP2[X1] + LineP1[X1];
				int PixelCount = (X2 - X1) * (Y2 - Y1);					//	有效的像素数
				LinePD[X] = (Sum + (PixelCount >> 1)) / PixelCount;		//	四舍五入
			}
		}
	}
	else if (Channel == 3)
	{
		GetRGBIntegralImage(Src, Integral, Width, Height, Stride);
		#pragma omp parallel for
		for (int Y = 0; Y < Height; Y++)
		{
			int Y1 = max(Y - Radius, 0);
			int Y2 = min(Y + Radius + 1, Height);
			int *LineP1 = Integral + Y1 * (Width + 1) * 3;
			int *LineP2 = Integral + Y2 * (Width + 1) * 3;
			unsigned char *LinePD = Dest + Y * Stride;
			for (int X = 0; X < Width; X++)
			{
				int X1 = max(X - Radius, 0);
				int X2 = min(X + Radius + 1, Width);
				int Index1 = X1 * 3;
				int Index2 = X2 * 3;
				int SumB = LineP2[Index2 + 0] - LineP1[Index2 + 0] - LineP2[Index1 + 0] + LineP1[Index1 + 0];
				int SumG = LineP2[Index2 + 1] - LineP1[Index2 + 1] - LineP2[Index1 + 1] + LineP1[Index1 + 1];
				int SumR = LineP2[Index2 + 2] - LineP1[Index2 + 2] - LineP2[Index1 + 2] + LineP1[Index1 + 2];
				int PixelCount = (X2 - X1) * (Y2 - Y1);
				LinePD[0] = (SumB + (PixelCount >> 1)) / PixelCount;
				LinePD[1] = (SumG + (PixelCount >> 1)) / PixelCount;
				LinePD[2] = (SumR + (PixelCount >> 1)) / PixelCount;
				LinePD += 3;
			}
		}
	}
	free(Integral);
}

效果演示

python演示:

import cv2


def integral_rgb(img_path):
    image = cv2.imread(img_path)

    image_integral = cv2.integral(image, cv2.CV_32F)
    cv2.normalize(image_integral, image_integral, 0, 255, cv2.NORM_MINMAX, -1)
    image_integral_norm = cv2.convertScaleAbs(image_integral)

    cv2.imwrite("./image.png", image)
    cv2.imwrite("./image_integral_norm.png", image_integral_norm)
    cv2.imshow("image", image)
    cv2.imshow("image_integral_norm", image_integral_norm)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


def integral_gray(img_path):
    image = cv2.imread(img_path, 0)

    image_integral = cv2.integral(image, cv2.CV_32F)
    cv2.normalize(image_integral, image_integral, 0, 255, cv2.NORM_MINMAX, -1)
    image_integral_norm = cv2.convertScaleAbs(image_integral)

    cv2.imwrite("./gray_image.png", image)
    cv2.imwrite("./gray_image_integral_norm.png", image_integral_norm)
    cv2.imshow("gray_image", image)
    cv2.imshow("gray_image_integral_norm", image_integral_norm)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


if __name__ == '__main__':
    img_path = r'C:\Users\xxx\Desktop\test.png'
    integral_rgb(img_path)
    integral_gray(img_path)

RGB图:
在这里插入图片描述

灰度图:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SongpingWang

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值