opencv 4매트 기본동작 3 (하이패스 필터, 로우패스 필터, 콘트라스트 조정)

이미지 필터링은 하이패스 필터링과 로우패스 필터링으로 나뉘는데, 하이패스 필터링은 그래픽의 가장자리를 찾는 데 사용되며, 로우패스 필터링은 이미지 노이즈 제거 및 이미지 블러링에 사용됩니다. 여기서 주파수는 변화(인근 픽셀 값의 변화)를 의미하고, 하이패스 필터는 큰 변화(즉, 이미지의 가장자리)의 통과를 의미한다(로우패스 필터는 작은 변화의 통과  (즉, 이미지의 그래픽) 고역 통과 필터 부분에는 Sobel, Scharr, Laplacian, canny 및 기타 방법이 포함되며 저역 통과 필터링 부분에는 평균 필터링, 상자 필터링, 중앙값 필터링이 포함됩니다 . 필터링, 가우시안 필터링 및 양방향 필터링 대비 조정은 이미지의 특정 영역의 픽셀 값을 수정하여 이미지를 만드는 것입니다. , 비선형 변화 및 히스토그램 평준화.

1. 하이패스 필터링

고역 통과 필터에는 Sobel, Scharr, Laplacian, canny 등이 있으며, 이들 필터의 특징은 영상의 고주파 부분은 통과시키고 영상의 저주파 부분은 걸러내는 특성)이고, 이 필터 값의 합은 0입니다. 에지 기울기를 계산할 때 노이즈 데이터의 영향을 피하기 위해 일부 저역 통과 필터를 사용하여 노이즈를 제거할 수 있습니다(예: 가우시안 필터링). 필터링 시 결과 값이 255보다 클 수 있으므로(CV_8U 범위 초과) 결과 데이터 유형은 일반적으로 16S이며 16S 범위는 convertScaleAbs 함수를 통해 CV_8U로 압축해야 합니다.

1.1 소벨 연산자와 샤르 연산자

노이즈에 대한 적용성이 높은 1차 미분 연산자로 먼저 내부적으로 가우시안 필터링을 이용하여 노이즈를 필터링한 후 1차 미분을 통해 영상의 에지를 구한다. [컨볼루션 커널 크기를 -1로 설정하면 자동으로 Scharr 필터 알고리즘 사용 ] 소벨 연산자에 대한 자세한 내용은 아래 그림과 같으며, 왼쪽 그림은 x 방향의 연산자(수직 기울기 구함) , 오른쪽 그림은 y 방향의 연산자(가로 방향의 기울기 구함)

Sobel 필터 연산자를 사용하는 코드는 다음과 같습니다.Sobel은 가로 방향의 기울기세로 방향의 기울기를 계산할 수 있습니다 .구한 기울기 값이 음수가 될 수 있으므로 convertScaleAbs를 사용하여 구해야 합니다. 절대값 . 최종 그래디언트 결과는 addWeighted 함수를 사용하여 가중치를 부여하고 합산해야 합니다 .

#include<iostream>  
#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc/imgproc.hpp>
 
using namespace std;
using namespace cv;
 
int scale = 1;
int delta = 0;
int ddepth = CV_16S;
 
int main()
{
    // 读入一张图片  
    Mat image = imread("C:\\Users\\aaa\\Pictures\\car1.png");
    //彩色图像转灰度图像
    cvtColor(image, image, COLOR_BGR2GRAY);
    imshow("原图", image);
     
    Mat grad_x, grad_y;
    Mat abs_grad_x, abs_grad_y;
     
    //求 X方向梯度,竖直边缘
    Sobel(image, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT);
    //求 Y方向梯度,水平边缘
    Sobel(image, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT);
    //将中间结果转换到 CV_8U:
    convertScaleAbs(grad_x, abs_grad_x);
    imshow("x", abs_grad_x);
    convertScaleAbs(grad_y, abs_grad_y);
    imshow("y", abs_grad_y);
    //将两个方向的梯度相加来求取近似 
    addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, image);
 
    imshow("sobel", image);
 
     
    waitKey(0);
}
 

 코드 실행 효과는 다음과 같습니다. 

Sobel 연산자는 이미지의 가장자리를 효과적으로 추출할 수 있지만 이미지의 약한 가장자리를 추출하는 데는 덜 효과적입니다. 따라서 약한 에지를 효과적으로 추출하기 위해서는 픽셀 값 사이의 간격을 늘려야 하므로 Scharr 연산자를 도입하였고 그 구조는 아래 그림과 같다.

 Scharr 연산자는 Sobel 연산자의 차이점을 개선한 것이므로 이미지의 가장자리를 감지하는 원리와 사용법은 둘 모두 동일합니다. Scharr 연산자의 에지 검출 필터의 크기는 3×3이므로 Scharr 필터라고도 합니다. 픽셀 값의 차이는 필터의 가중치 계수를 증폭하여 증가시킬 수 있습니다. [OpenCV 4 개발 상세 설명] 에서 참조 Scharr Operator-Knowledge

1.2  라플라시안 연산자

  라플라시안은 이미지 에지 검출에 적용할 수 있습니다. OpenCV에서는 커널 크기가 3*3일 때 아래 그림과 같이 두 개의 커널 연산자가 지원됩니다. Laplacian 연산자는 수평 방향과 수직 방향의 기울기를 동시에 계산할 수 있으며 무방향성의 특징을 가지고 있습니다 . 라플라시안 연산자는 노이즈에 민감한 2차 미분 연산자이므로 가우시안 필터링(노이즈 제거)과 함께 사용하는 경우가 많습니다.

호출 코드는 다음과 같습니다.

  Mat image = imread("C:\\Users\\aaa\\Pictures\\car1.png");
    //彩色图像转灰度图像
    cvtColor(image, image, COLOR_BGR2GRAY);
    imshow("原图", image);
     
    Mat grad;
    Laplacian(image, grad, CV_8U);
    convertScaleAbs(grad, grad);
    imshow("Laplacian", grad);
     
    waitKey(0);

코드 결과는 다음과 같습니다 

 1.3  캐니 오퍼레이터

캐니 연산자는 노이즈 제거 = "진폭 및 방향 계산 ="비최대 억제 = "히스테리시스 임계값"의 4단계로 구현되며, 계산 시 x 및 y 방향의 기울기 값을 계산하기 위해 소벨 연산자를 사용합니다 . 진폭과 방향. 자세한 내용은 다음 블로그 Canny Edge Detection of OpenCV(C++ 구현) https://blog.csdn.net/xddwz/article/details/111585648 에 나와 있습니다.

 위의 세 가지 필터와 비교하여 cany의 계산 프로세스가 더 복잡하고 계산량이 더 큽니다. 사용 코드와 실행 결과는 아래와 같습니다.

   // 读入一张图片  
    Mat image = imread("C:\\Users\\aaa\\Pictures\\car1.png");
    //彩色图像转灰度图像
    cvtColor(image, image, COLOR_BGR2GRAY);
    imshow("原图", image);
     
    Mat grad;
/*
void Canny( InputArray image, OutputArray edges,
                         double threshold1, double threshold2,
                         int apertureSize = 3, bool L2gradient = false )
*/
    Canny(image, grad, 150, 100, 3);
    imshow("grad", grad);
     
    waitKey(0);

2. 저역 통과 필터링

OpenCV에서 일반적으로 사용되는 저역 통과 필터는 평균 필터, 상자 필터, 중앙값 필터, 가우시안 필터 및 양방향 필터이며 주로 이미지의 노이즈를 제거하는 데 사용됩니다.

2.1 평균 필터링 및 박스 필터링

평균 필터링은  선명한 이미지 노이즈를 제거하고 이미지를 매끄럽게 하고 흐릿하게 만드는 등의 기능을 수행하는 데 도움이 될 수 있습니다. 이상적인 평균 필터는 이미지의 각 픽셀을 각 픽셀과 주변 픽셀에 대해 계산된 평균값으로 대체하는 것입니다.

평균 필터링에는 평균 평균 필터링과 가중 평균 필터링이 있습니다. 각각 다음과 같이:

      왼쪽은 평균 평균 필터링이고 오른쪽은 가중 평균 필터링입니다. 

 박스 필터링 과 평균 필터링의 원리는 유사하며, 정규화 후 박스 필터링의 효과는 동일한 컨볼루션 커널 크기를 가진 평균 필터링과 동일합니다. OpenCV에서 상자 필터의 커널 크기는 다음 그림과 같이 상자의 행과 열의 수를 나타냅니다.

 호출 코드는 다음과 같습니다.

#include <iostream>
#include <opencv2\opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
	//---------------------------用于方框滤波的图像--------------------
	Mat img = imread("C:\\Users\\aaa\\Pictures\\timg.jpg",0);
	resize(img, img, { 500,300 });

	//将CV_8U类型转换成CV_32F类型,避免计算后的数据过大
	Mat equalImg_32F;
	img.convertTo(equalImg_32F, CV_32F, 1.0 / 255);
	Mat resultNorm, result, equalImg_32FSqr;
	//--------------------------方框滤波boxFilter----------------------
	boxFilter(img, resultNorm, -1, Size(3, 3), Point(-1, -1), true);  // 进行归一化,则为均值滤波
	boxFilter(img, result, -1, Size(3, 3), Point(-1, -1), false);     // 不进行归一化
	//----------------------方框滤波sqrBoxFilter()---------------------
	//对每个像素数值的平方求和/求均值
	sqrBoxFilter(equalImg_32F, equalImg_32FSqr, -1, Size(3, 3), Point(-1, -1), true, BORDER_CONSTANT);
	//-------------------------显示处理结果----------------------------
	imshow("原始图像", img);
	imshow("归一化", resultNorm);
	imshow("不归一化", result);
	imshow("平方和求均值", equalImg_32FSqr);
	waitKey(0);
	return 0;
}

코드 실행 효과는 다음과 같습니다. 

 2.2 중앙값 필터링 

특정 조건에서 중간 필터는 박스 필터 및 평균 필터와 같은 일반적인 선형 필터로 인해 발생하는 이미지 세부 사항의 흐림을 극복할 수 있으며 펄스 간섭 및 이미지 스캐닝 노이즈를 필터링하는 데 매우 효과적이며 일반적으로 에지 정보를 보호하는 데 사용됩니다. 에지 보존 기능은 에지 블러링을 원하지 않는 경우에 유용하며 매우 고전적인 스무딩 노이즈 처리 방법입니다. 다음 내용은 Opencv의 이미지 필터링에서 참조했습니다. 5. 중간 필터링(cv2.medianBlur)_Justth.의 블로그-CSDN blog_opencv 중간 필터링 이전에 소개된 평균 필터링, 상자 필터링 및 가우시안 필터링은 모두 선형 필터링 방법입니다. 선형 필터링의 결과는 모든 픽셀 값의 선형 조합이므로 노이즈가 포함된 픽셀도 고려되며 노이즈가 제거되지 않고 더 부드러운 방식으로 존재합니다. 이때 비선형 필터링을 사용하면 효과가 더 좋을 수 있습니다. 중앙값 필터링은 위에서 설명한 필터링 방법과 다르며 더 이상 가중 평균으로 필터링 결과를 계산하지 않습니다. 현재 픽셀의 픽셀 값을 이웃에 있는 모든 픽셀 값의 중앙값으로 대체합니다. 5.1 원리 소개 미디안 필터는 현재 픽셀과 그 주변 픽셀(총 홀수 픽셀)의 픽셀 값을 가져와 이 픽셀 값을 정렬한 다음 중간 위치의 픽셀 값을 픽셀 값으로 사용합니다. 현재 픽셀 . 다음 순간을 위해.. https://blog.csdn.net/qq_49478668/article/details/123485382

 중앙값 필터는 현재 픽셀과 그 주변 픽셀( 총 홀수 픽셀 이 있음)의 픽셀 값을 가져와 이 픽셀 값을 정렬한 다음 중간 위치의 픽셀 값을 현재 픽셀의 픽셀 값으로 사용합니다. . 다음 행렬의 경우:

 이웃을 3×3 크기로 설정하고 3×3 이웃에 있는 픽셀의 픽셀 값을 정렬(오름차순 및 내림차순 모두) 오름차순으로 정렬한 후 시퀀스 값은 [66, 78,90,91, 93,94,95,97,101]. 이 시퀀스에서 중심 위치(중심점 또는 중간점이라고도 함)의 값은 "93"이므로 원래 픽셀 값 78을 현재 지점의 새 픽셀 값으로 이 값으로 바꿉니다. 중앙값 필터링 효과는 다음과 같습니다.

 호출 코드는 다음과 같습니다.

#include <iostream>
#include <opencv2\opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("C:\\Users\\aaa\\Pictures\\timg.jpg",0);
	resize(img, img, { 500,300 });
	Mat grayResult;
	medianBlur(img, grayResult , 3);
	imshow("原始图像", img);
	imshow("中值滤波", grayResult);
	waitKey(0);
	return 0;
}

코드 연산 효과는 다음과 같습니다. 

 2.3 가우시안 필터링 

가우시안 필터링은 이미지 밸런스, 이미지 블러링 또는 이미지 노이즈 제거에 사용됩니다.가중 필터링 구현입니다.가우시안 필터링의 연산자는 가우시안 분포 함수에서 계산됩니다(가운데가 가장 중요하고, 바깥쪽이 두 번째임)【 가우스 분포에는 표준편차와 분산이라는 두 가지 매개변수가 있습니다]. 가우시안 필터링의 연산자는 각 위치에 서로 다른 가중치를 부여하는 것으로, 중간에 있는 가중치가 가장 크고 가장자리가 두 번째이며 모든 가중치의 합이 1입니다.

가우스 필터링을 사용하는 코드와 효과는 다음과 같습니다. 

    Mat img = imread("C:\\Users\\aaa\\Pictures\\timg.jpg",0);
	resize(img, img, { 500,300 });
	Mat out;
	GaussianBlur(img, out, cv::Size(5, 5), 3, 3);
	imshow("原始图像", img);
	imshow("out", out);
	waitKey(0);

2.4 양방향 필터링

Bilateral 필터(Bilateral filter)는 비선형 필터링 방식으로, bilateral filter의 장점은 edge 보존을 할 수 있다는 점이다. 일반적으로 가우시안 필터링은 노이즈 감소에 사용되며 가장자리를 분명히 흐리게 하고 고주파 세부 사항에 대한 보호 효과는 명확하지 않지만 양방향 필터링을 사용하면 가우시안 필터링의 노이즈 감소 효과를 얻을 수 있으며 잘 보존할 수 있습니다. 필터가 가우시안 필터보다 하나 더 많은 가우시안 분산 sigma-d를 갖기 때문입니다. 내용은 OpenCV Study Notes (7) Median and Bilateral Filtering - Short Book 에서 참조합니다.

양방향 필터링을 사용하는 코드 및 효과는 다음과 같습니다. 

Mat img = imread("C:\\Users\\aaa\\Pictures\\timg.jpg",0);
	resize(img, img, { 500,300 });
	Mat out;
	/*
	bilateralFilter( InputArray src, OutputArray dst, int d,
                                   double sigmaColor, double sigmaSpace,
                                   int borderType = BORDER_DEFAULT )
	*/
	bilateralFilter(img, out, 25, 25 * 2, 25 / 2);
	imshow("原始图像", img);
	imshow("out", out);
	waitKey(0);

3. 대비 조정

대비 조정은 이미지의 특정 영역의 픽셀 값을 수정하여 이미지의 대비를 변경하는 것입니다. 대비 향상은 밝은 부분을 더 밝게 하고 어두운 부분을 더 어둡게 만드는 것이고, 대비 향상 감소는 밝은 부분을 더 어둡게 하고 어두운 부분을 더 밝게 만드는 것입니다. 구체적인 콘트라스트 조정 방법은 다음과 같습니다: 수치 가산 및 빼기(콘트라스트는 향상될 수 없지만 이미지는 전체적으로 밝게 또는 어둡게만 가능), 선형 변경(픽셀 값은 선형 함수, y=ax+b에 의해 변경됨) , a>1인 경우 대비 향상, a<1인 경우 대비 약화), 비선형 변경(로그 변경, 문법 변경, 사용자 정의 변경 기능), 히스토그램 균등화 및 기타 수단.

3.1 숫자의 덧셈과 뺄셈

매트의 가감으로 영상의 밝기를 조절할 수 있습니다.(대비 조절 불가) 덧셈 결과가 255를 초과하면 255, 뺄셈 결과가 0 미만이면 0입니다.

테스트 코드는 다음과 같습니다

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include<opencv2/core/core.hpp>
#include<iostream>
 
using namespace std;
using namespace cv;
int main()
{
	Mat srcImage;
	srcImage = imread("C:/Users/aaa/Pictures/b.jpg", 0);
	resize(srcImage, srcImage,{},0.5,0.5);
	imshow("img", srcImage);
	Mat img_bl,img_an;
	//
	img_an = srcImage - 50;//减=》变暗
	img_bl = srcImage + 50;//加=》变亮
	imshow("img-50", img_an);
	imshow("img+50", img_bl);
	waitKey(0);
	return 0;
}

 코드 실행 효과는 다음과 같습니다. 

3.2 선형 연산

y=ax+b의 선형 함수 매핑을 통해 픽셀 값을 수정합니다. a>1은 대비를 향상시키고 a<1은 대비를 감소시킵니다.

테스트 코드는 다음과 같습니다

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include<opencv2/core/core.hpp>
#include<iostream>
 
using namespace std;
using namespace cv;
int main()
{
	Mat srcImage;
	srcImage = imread("C:/Users/aaa/Pictures/b.jpg", 0);
	resize(srcImage, srcImage,{},0.5,0.5);
	imshow("img", srcImage);
	Mat img_bl,img_an;
	//
	img_an = srcImage*0.8 + 10;//a<1=》变暗
	img_bl = srcImage*1.5 - 30;//a>1=》变亮
	imshow("img*0.6 + 10", img_an);
	imshow("img*1.2 - 30", img_bl);
	waitKey(0);
	return 0;
}

코드 실행 효과는 다음과 같습니다. 

3.3 비선형 변환

opencv에서 일반적인 비선형 변환은 대수 변환(볼록한 함수, y=x 함수 이미지 위)과 감마 변환(감마 값이 변경됨에 따라 y=x 함수 이미지 아래 또는 위에 있을 수 있음)입니다. 비선형 기능을 사용자 지정하여 이미지의 밝기를 조정합니다.

대수 변화에 대한 코드인 감마는 아래와 같습니다. 대수변화를 수행할 때 대수변화에 해당하는 값 범위는 0~255이지만 대수변화 후의 출력값 범위는 255를 초과하므로 정규화 기능을 사용하여 값 범위를 0~255로 압축해야 함을 유의해야 한다. . 플로트형 매트의 경우 opencv가 이해하는 범위는 [0,1]이고 1을 초과하는 부분은 흰색이므로 CV_32F를 CV_8U로 변환(또는 normalize 함수를 사용하여 값 범위를 [0 ,1] )

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include<opencv2/core/core.hpp>
#include<iostream>
 
using namespace std;
using namespace cv;
 
int main()
{
	Mat srcImage;
	srcImage = imread("C:/Users/aaa/Pictures/b.jpg", 0);
	resize(srcImage, srcImage,{},0.5,0.5);
	imshow("img", srcImage);
	
	//log变化、对数变化,使图像变亮
	Mat img_log;
	srcImage.convertTo(srcImage, CV_32F);
	log(srcImage, img_log);//log变化后图像值会出现小数,log函数的输出范围超出0~255
	normalize(img_log, img_log, 0, 255, NORM_MINMAX);//将log函数的输出压缩到0~255内
	img_log.convertTo(img_log, CV_8U);//因为图像是CV_32F,且值域超出0~1
 
	//gamma变化
	Mat g2_05=gamma_mat(srcImage, 2, 0.5);
	Mat g1_13 = gamma_mat(srcImage, 2, 1.3);
	imshow("img_log", img_log);
	imshow("g2_05", g2_05);
	imshow("g1_13", g1_13);
	waitKey(0);
	return 0;
}

gamma_mat 함수의 구현은 다음과 같으며, 감마 함수의 변경은 0과 1 사이의 값 범위를 대상으로 하므로 mat의 픽셀 값(값 범위는 0~255)을 정규화해야 함을 유의해야 합니다(즉, CV_8U를 CV_64F로 한 다음 255로 나눕니다) . 연산 결과도 0과 1 사이가 아니므로 정규화(또는 255로 정규화)해야 합니다.

Mat gamma_mat(Mat src,float c, float gamma) {
	//伽马变换
	Mat gamma_image;  //归一化图像
	src.convertTo(src, CV_64F);
	src = src / 255;
	int height = src.rows;
	int width = src.cols;
	gamma_image.create(src.size(), CV_64F);
	for (int i = 0; i < height; i++)
	{
		for (int j = 0; j < width; j++)
		{
			gamma_image.at<double>(i, j) = c*pow(src.at<double>(i, j), gamma);
 
		};
	};
    //方式一  归一化
    normalize(gamma_image, gamma_image, 0, 1, NORM_MINMAX);
    //方式二  归255 转CV_8U
	//normalize(gamma_image, gamma_image, 0, 255, NORM_MINMAX);
	//gamma_image.convertTo(gamma_image, CV_8U);
    //方式三  归255 转CV_8U
	//gamma_image.convertTo(gamma_image, CV_8U, 255, 0);
	return gamma_image;
}

3.4 히스토그램 평준화

히스토그램 평활화를 사용하면 이미지 대비를 향상시킬 수 있습니다 자세한 개념은 다음 링크를 참조하십시오:
OpenCV 히스토그램 평활화_Yang Jian의 블로그-CSDN blog_opencv 히스토그램 평활화 기사 디렉토리 히스토그램 평활화 소개 이미지의 히스토그램이란 무엇입니까?히스토그램 평활화가 무엇인지 더 생생하게 설명하십시오 ? 히스토그램 평준화는 어떻게 구현됩니까? 히스토그램 평활화의 역할 히스토그램 평활화 단계 관련 APIequalizeHist 코드 예제 히스토그램 평활화 소개 이미지의 히스토그램이란 무엇입니까? 발생 빈도를 이미지 히스토그램-히스토그램이라고 합니다. 히스토그램은 이미지 그레이 레벨의 분포를 반영합니다. 이미지의 통계적 특징입니다. 간단히 말해서 히스토그램은 이미지의 픽셀 강도 분포를 그래픽으로 표현한 것으로 각 강도 값의 픽셀 수를 계산합니다. 예를 들어 아래 사진에서 왼쪽 사진은 gray_1671465600 https://blog.csdn.net/weixin_45525272/article/details/122663041

그레이스케일 히스토그램 균등화는 equalizeHist(in_mat,out_mat)를 직접 호출할 수 있으며 구체적인 호출 사례는 다음과 같습니다. 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include<opencv2/core/core.hpp>
#include<iostream>
 
using namespace std;
using namespace cv;
 
int main()
{
	Mat srcImage;
	srcImage = imread("C:/Users/aaa/Pictures/a.jpg", 0);
	resize(srcImage, srcImage,{},0.5,0.5);
	imshow("原始图", srcImage);
	Mat new_img;
	equalizeHist(srcImage, new_img);
	imshow("经过直方图均衡化后的图", new_img);
	waitKey(0);
	return 0;
}

코드 실행 효과는 다음과 같습니다. 

컬러 이미지 히스토그램 균등화는 특히 bgr 이미지의 경우 각 채널을 직접 균등화할 수 없습니다. 이러한 종류의 bgr 이미지를 위해서는 먼저 색 공간을 BGR에서 HSV로 변환한 다음 이미지를 3개의 매트(분포 객체 H, S 및 V 3개 채널)로 나누고 해당 매트에서 히스토그램 평활화를 수행해야 합니다. 브이채널. 마지막으로 H, S, V의 3채널 단일 채널 매트를 3채널 매트로 병합한 다음 hsv 색 공간의 매트를 bgr의 매트로 변환합니다. 구체적인 동작은 다음과 같다

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include<opencv2/core/core.hpp>
#include<iostream>
 
using namespace std;
using namespace cv;
Mat brgEqualizeHist(Mat bgr) {
	Mat hsvImg, dstImage;
	cvtColor(bgr, hsvImg, COLOR_BGR2HSV);
	//定义一个channels储存分离后的通道
	vector<Mat> channels;
	//H,S,V三个通道
	Mat h, s, v;
	//分离图像
	split(hsvImg, channels);
 
	h = channels.at(0);
	s = channels.at(1);
	v = channels.at(2);
	//对V通道就行直方图均衡化,使图像的亮度变得均衡
	equalizeHist(v, v);
 
	//将直方图均衡化的通道合并起来
	merge(channels, hsvImg);
	cvtColor(hsvImg, dstImage, COLOR_HSV2BGR);
	return dstImage;
}
int main()
{
	Mat srcImage;
	srcImage = imread("C:/Users/aaa/Pictures/a.jpg", 1);
	resize(srcImage, srcImage,{},0.5,0.5);
	imshow("原始图", srcImage);
	Mat new_bgr = brgEqualizeHist(srcImage);
	imshow("经过直方图均衡化后的图", new_bgr);
	waitKey(0);
	return 0;
}

 코드 실행 효과는 다음과 같습니다.

추천

출처blog.csdn.net/m0_74259636/article/details/128587670