1、灰度直方图
#灰度直方图
import numpy as np
import matplotlib.pyplot as plt
import cv2
import sys
def calGrayHist(img):
rows,cols=img.shape[:2]
cnt=np.zeros([256],dtype=np.uint32)
for i in range(rows):
for j in range(cols):
cnt[img[i][j]]+=1
return cnt
if __name__=="__main__":
img=cv2.imread("1.jpg")
grayHist=calGrayHist(img)
cv2.imshow('1',img)
cv2.waitKey(2000)
xrange=range(256)
plt.plot(xrange,grayHist,'+',linewidth=2,c='green')
y_maxValue=np.max(grayHist)
print(y_maxValue)
plt.axis([0,255,0,y_maxValue])
plt.xlabel('gray Level')
plt.ylabel('number of pixels')
plt.show()
#Matplotlib 自带的库
import sys
import numpy as np
import matplotlib.pyplot as plt
from cv2 import *
if __name__=="__main__":
img=imread("1.jpg",IMREAD_GRAYSCALE)
rows,cols=img.shape[:2]
print(img.shape)
pixelSequence=img.reshape([rows*cols])
numberBins=256
histogram,bins,patch=plt.hist(pixelSequence,numberBins,facecolor='black',histtype='bar')
plt.xlabel(u"gray Level")
plt.ylabel(u'number of pixels')
y_maxValue=np.max(histogram)
print(y_maxValue)
plt.axis([0,256,0,y_maxValue])
plt.show()
2、线性变换
O=a*I+b
a=1,b=0:原图的一个副本,a>1,则输出图像O对比度比I增大,0<a<1,O的对比度比I小。
b的值影响图像的亮度,当b>0时,亮度增加;b<0时亮度减少。
import cv2
import numpy as np
img=cv2.imread("1.jpg")
a=2
t=float(a)*img
t[t>255]=255
t=np.round(t)
t=t.astype(np.uint8)
cv2.imshow("img",img)
cv2.imshow('t',t)
cv2.waitKey(0)
cv2.destroyAllWindows()
#include<opencv2\core\core.hpp>
#include<opencv2\highgui.hpp>
#include<opencv2\imgproc.hpp>
using namespace cv;
int main()
{
Mat img = imread("1.jpg",CV_LOAD_IMAGE_GRAYSCALE);
int rows = img.rows;
int cols = img.cols;
//线性变换第一种,通过Mat的成员函数 Mat::converTo(OutputArray m,int rtype,double alpha=1,double beta=0);
Mat out;
img.convertTo(out,CV_8UC1,2.0,0);
imshow("out1", out);
//线性变化第二种,使用乘法运算符,无论常数是什么类型,输出的矩阵的数据类型总是和输入矩阵类型相同。
Mat out1;
out1 = 2 * img+100;
imshow("out2",out1);
//线性变化第三种,基于OpenCV提供的函数:convertScaleAbs(InputArray src,OutputArray dst,double alpha=1,double beta=0);
Mat out2;
convertScaleAbs(img,out2,2,10);
imshow("out3", out2);
waitKey(0);
}
3、直方图正规化
import numpy as np
import cv2
import Hist
img=cv2.imread("1.jpg")
Hist.Hist(img,"RAW")
mx=np.max(img)
mi=np.min(img)
cv2.imshow("1",img)
print(mx,mi)
outx=255
outi=0
a=float(outx-outi)/(mx-mi)
b=outi-a*mi
print(a,b)
out=a*img+b
out[out>255]=255
out=np.round(out)
out=np.uint8(out)
cv2.imshow("out",out)
Hist.Hist(out,"After")
cv2.waitKey(0)
#include<opencv2\core\core.hpp>
#include<opencv2\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
using namespace cv;
/*
void minMaxLoc(InputArray src,dounle *minVal,double *maxVal,Point *minLoc=0,Point *maxLoc=0,InputArray mask=noArray());
src :输入矩阵
minVal :最小值,double类型指针
maxVal :最大值,double类型指针
minLoc :最小位置的索引,Point类型的指针
maxLoc :最大位置的索引,Point类型的指针
*/
int main()
{
Mat img = imread("1.jpg",CV_LOAD_IMAGE_GRAYSCALE);
if (!img.data)
return -1;
double Imax, Imin;
minMaxLoc(img,&Imin,&Imax,NULL,NULL);
double Omax = 255, Omin = 0;
double a = (Omax - Omin) / (Imax - Imin);
double b = Omin - a*Imin;
Mat out;
convertScaleAbs(img, out, a, b);
imshow("RAW", img);
imshow("OUT", out);
waitKey(0);
}
4、正规划normalize
import cv2
import numpy as np
from Hist import *
img=cv2.imread('1.jpg',cv2.IMREAD_ANYCOLOR)
Hist(img,"RAW")
dst=img
cv2.normalize(img,dst,255,0,cv2.NORM_MINMAX,cv2.CV_8U)
Hist(dst,"dst")
cv2.imshow('raw',img)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
#include<opencv2\core.hpp>
#include<opencv2\highgui.hpp>
#include<opencv2\imgproc.hpp>
using namespace cv;
/*
void normalize(InputArray src,OutputArray dst,double alpha=1,double beta=0,int norm_type=NORM_L2,int type=-1,InputArray mask=noArray());
src :输入矩阵
dst :结构元
alpha :结构元的锚点
beta :腐蚀操作的次数
norm_type:边界扩充类型(NORM_type=NORM_L1 NORM_L2 NORM_MINMAX)
dtype :边界扩充值
*/
int main()
{
Mat src = imread("1.jpg",CV_LOAD_IMAGE_ANYCOLOR);
if (!src.data)
return -1;
Mat dst;
normalize(src,dst,255,0,NORM_MINMAX,CV_8U);
imshow("原图",src);
imshow("正则化后",dst);
waitKey(0);
}
5、伽马变换
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
using namespace cv;
/*
输入图像,首先将其灰度值归一化到[0,1]范围内,对于8位图来说,除以255即可,
I(r,c)代表归一化后的第r行第c列的灰度值,输出图像记为O,O(r,c)=I(r,c)^r
当r=1时,图像不变,如果图像整体或者感兴趣区域较暗,则令0<r<1,可以增加图像对比度,
相反,如果图像整体或者感兴趣区域较亮,则令r>1可以降低图像对比度。
综上:
1、对图像进行伽马变换时,首先将灰度值转化到[0,1]范围
2、进行幂运算
*/
int main()
{
Mat img = imread("1.jpg",CV_LOAD_IMAGE_GRAYSCALE);
Mat dst,out;
img.convertTo(dst, CV_64F, 1.0 / 255.0, 0);
double gamma = 0.5;
pow(dst, gamma, out);
//std::cout << out << std::endl;
imshow("out", out);
waitKey(0);
Mat tmp;
out.convertTo(tmp, CV_8U, 255, 0);
imwrite("out.jpg", tmp);
system("pause");
return 0;
}
import cv2
import numpy as np
img=cv2.imread("1.jpg",cv2.IMREAD_GRAYSCALE)
out=img/255.0
gamma=0.5
out=np.power(out,gamma)
out=out*255.0
out=np.round(out)
out=out.astype(np.uint8)
cv2.imshow('img',img)
cv2.imshow('out',out)
cv2.waitKey(0)
cv2.destroyAllWindows()
6、全局直方图均衡化
import cv2
import numpy as np
import math
from calcGrayHist import *
"""
1、计算图像的灰度直方图
2、计算灰度直方图的累加直方图
3、根据累加直方图和直方图均衡化原理得到输入灰度级和输出灰度级之间的映射关系。
4、根据第三步得到的灰度级映射关系,循环得到输出图像的每一个像素的灰度级
"""
def equalHist(img):
rows,cols=img.shape
grayHist=Hist(img)
zeroCumuMoment=np.zeros([256],np.uint32)
zeroCumuMoment[0]=grayHist[0];
for i in range(1,256):
zeroCumuMoment[i]=zeroCumuMoment[i-1]+grayHist[i]
outPut_q=np.zeros([256],np.uint8)
cofficient=256.0/(rows*cols)
for i in range(256):
q=float(zeroCumuMoment[i])*cofficient-1
if q>=0:
outPut_q[i]=math.floor(q)
else:
outPut_q[i]=0
out=np.zeros(img.shape,np.uint8)
for r in range(rows):
for c in range(cols):
out[r][c]=outPut_q[img[r][c]]
return out
if __name__=="__main__":
img=cv2.imread("1.jpg",cv2.IMREAD_GRAYSCALE)
out=equalHist(img)
print(out)
cv2.imshow("raw",img)
cv2.imshow("equalHist",out)
cv2.waitKey(0)
cv2.destroyAllWindows()
#include<opencv2\core.hpp>
#include<opencv2\highgui.hpp>
#include<opencv2\imgproc.hpp>
#include<iostream>
using namespace cv;
Mat equalHist(Mat img);
Mat calcGrayHist(Mat img);
int main()
{
Mat img = imread("1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
std::cout << img.type() << std::endl;
if (!img.data)
return -1;
Mat out = equalHist(img);
imshow("raw", img);
imshow("equalHist", out);
waitKey(0);
return 0;
}
Mat equalHist(Mat img)
{
CV_Assert(img.type()==CV_8UC1);//若括号中的表达式值为false,则返回一个错误信息。
int rows = img.rows;
int cols = img.cols;
//求图像灰度直方图
Mat grayHist = calcGrayHist(img);
//累加灰度直方图
Mat zeroCumuMoment = Mat::zeros(Size(256,1),CV_32SC1);
zeroCumuMoment.at<int>(0,0)= grayHist.at<int>(0,0);
for (int i = 1; i < 256; i++)
zeroCumuMoment.at<int>(0, i) = zeroCumuMoment.at<int>(0, i - 1) + grayHist.at<int>(0, i);
//根据累加直方图得到输入灰度级和输出灰度级之间的映射关系
Mat outPut_q = Mat::zeros(Size(256,1),CV_8UC1);
float cofficient = 256.0 / (rows*cols);
for (int i = 0; i < 256; i++)
{
float q = cofficient*zeroCumuMoment.at<int>(0, i) - 1;
if (q >= 0)
outPut_q.at<uchar>(0, i) = uchar(floor(q));
else
outPut_q.at<uchar>(0, i) = 0;
}
//计算直方图均衡化后的图像
Mat equalHistImage = Mat::zeros(img.size(),CV_8UC1);
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
{
int p = img.at<uchar>(r, c);
equalHistImage.at<uchar>(r, c) = outPut_q.at<uchar>(0, p);
}
}
return equalHistImage;
}
Mat calcGrayHist(Mat img)
{
Mat cnt = Mat::zeros(Size(256,1),CV_32SC1);
int rows = img.rows;
int cols = img.cols;
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
{
cnt.at<int>(0, img.at<uchar>(i, j)) += 1;
}
return cnt;
}
7、限制对比度的自适应直方图均衡化
#include<opencv2\core.hpp>
#include<opencv2\highgui.hpp>
#include<opencv2\imgproc.hpp>
using namespace cv;
/*
自适应直方图均衡化首先将图像划分为不重叠的区域块,然后对每一个块分别进行直方图均衡化,
显然在没有噪声的情况下,每一个小区域的灰度直方图会被限制再一个小的灰度级范围内,
但是如果有噪声,会被放大。
为了避免出现这种情况,提出“限制对比度”(contrast Limiting),如果直方图的bin超过了设定好的“限制对比度”,
那么会被裁减,然后将裁剪的部分均匀分布到其他的bin。
OpenCV中提供的函数createCLAHE构建指向CLAHE对象的指针,默认设置“限制对比度”为40。
*/
int main()
{
Mat src = imread("1.jpg",CV_LOAD_IMAGE_GRAYSCALE);
Ptr<CLAHE> clahe = createCLAHE(2.0, Size(8, 8));
Mat dst;
clahe->apply(src, dst);
imshow("原图", src);
imshow("对比度增强",dst);
waitKey(0);
destroyAllWindows();
return 0;
}
import cv2
import numpy as np
if __name__=="__main__":
src=cv2.imread("1.jpg",cv2.IMREAD_GRAYSCALE)
clahe=cv2.createCLAHE(clipLimit=2.0,tileGridSize=(8,8))
dst=clahe.apply(src)
cv2.imshow("src",src)
cv2.imshow("clahe",dst)
cv2.waitKey(0)
cv2.destroyAllWindows()