兩者都是只對單通道使用,對多通道的話 就需要分離通道處理再合并通道
?兩種方法,第一個要運算次數太多了,第二個只需要查表
伽馬矯正函數,這里用第二種方法,且寫法有點高級
int gammaCorrection(cv::Mat srcMat, cv::Mat& dstMat, float gamma) {//建立查詢表unsigned char lut[256];for (int i = 0; i < 256; i++){//saturate_cast,防止像素值溢出,如果值<0,則返回0,如果大于255,則返回255lut[i] = saturate_cast<uchar>(pow((float)(i / 255.0f), gamma) * 255.0f);}srcMat.copyTo(dstMat);MatIterator_<uchar> it, end;for (it = dstMat.begin<uchar>(), end = dstMat.end<uchar>(); it != end; it++) {*it = lut[(*it)];}return 0;}
就是建立了查找表,然后計算查找表,再遍歷像素直接賦值查找表,就不用計算了。
int readType = 0;Mat srcMat = imread("kjy.jpg");resize(srcMat, srcMat,Size(srcMat.rows*0.5, srcMat.rows * 0.5));cv::Mat dstMat;float gamma = GAMMA_FACTOR;if (srcMat.type() == CV_8UC1){gammaCorrection(srcMat, dstMat, gamma);}else {Mat channel[3];Mat out[3];float hist[3][256];//通道分離split(srcMat, channel);for (int i = 0; i < 3; i++) {gammaCorrection(channel[i], out[i], gamma);}merge(out, 3, dstMat);}imshow("src", srcMat);imshow("dst", dstMat);waitKey(0);destroyAllWindows();
這就是grammar矯正的代碼
直方圖均衡化(只對單通道有效果)多通道的話先分離通道再合并一樣的
equalizeHist(srcMat, equalizeHistMat);
?
計算直方圖函數
int calcIntenHist(const cv::Mat src, float* dstHist)
{//輸入必為單通道圖if (src.type() != CV_8UC1) {return -1;}memset(dstHist, 0, sizeof(float) * 256);int height = src.rows;int width = src.cols;//指針遍歷for (int k = 0; k < height; k++){// 獲取第k行的首地址const uchar* inData = src.ptr<uchar>(k);//處理每個像素for (int i = 0; i < width; i++){int gray = inData[i];dstHist[gray]++;}}//直方圖歸一化float norm = height * width;for (int n = 0; n < 256; n++) {dstHist[n] = dstHist[n] / norm;}return 0;
}
?還進行了歸一化
直方圖畫畫函數
int drawIntenHist(cv::Mat& histMat, float* srcHist, int bin_width, int bin_heght)
{histMat.create(bin_heght, 256 * bin_width, CV_8UC3);histMat = Scalar(255, 255, 255);float maxVal = *std::max_element(srcHist, srcHist + 256);for (int i = 0; i < 256; i++) {Rect binRect;binRect.x = i * bin_width;float height_i = (float)bin_heght * srcHist[i] / maxVal;binRect.height = (int)height_i;binRect.y = bin_heght - binRect.height;binRect.width = bin_width;rectangle(histMat, binRect, CV_RGB(255, 0, 0), -1);}return 0;
}
?float height_i = (float)bin_heght * srcHist[i] / maxVal;是防止不夠高度大小 要進行的高度歸一
直方圖均衡化的完整代碼:
float srcHist[256];float dstHist[256];Mat dstHistMat;Mat srcHistMat;Mat histMat[3];Mat equalizeHistMat;cv::Mat dstMat1;int bin_width = 2;int bin_heigth = 100;if (srcMat.type() == CV_8UC1) {equalizeHist(srcMat, equalizeHistMat);imshow("src", srcMat);imshow("equalizeHistMat", equalizeHistMat);waitKey(0);destroyAllWindows();calcIntenHist(dstMat1, dstHist);drawIntenHist(dstHistMat, dstHist, 3, 100);imshow("dstMat hist", dstHistMat);calcIntenHist(srcMat, srcHist);drawIntenHist(srcHistMat, srcHist, 3, 100);imshow("srcMat hist", srcHistMat);waitKey(0);destroyAllWindows();}else{Mat channel[3];Mat out[3];float hist[3][256];split(srcMat, channel);for (int i = 0; i < 3; i++) {equalizeHist(channel[i], out[i]);calcIntenHist(out[i], hist[i]);drawIntenHist(histMat[i], hist[i], bin_width, bin_heigth);//按照channel編號命名窗口stringstream ss;ss << i;string histWindow = "Hist of chanel " + ss.str();string matWindow = "Image of chanel " + ss.str();imshow(histWindow, histMat[i]);imshow(matWindow, out[i]);}merge(out, 3, dstMat1);cv::Mat grayMat;cv::Mat graydstMat;cvtColor(srcMat, grayMat, CV_BGR2GRAY);cvtColor(dstMat1, graydstMat, CV_BGR2GRAY);//計算并繪制直方圖calcIntenHist(graydstMat, dstHist);drawIntenHist(dstHistMat, dstHist, 3, 100);imshow("dstMat", dstMat1);imshow("dstMat hist", dstHistMat);calcIntenHist(grayMat, srcHist);drawIntenHist(srcHistMat, srcHist, 3, 100);imshow("srcMat hist", srcHistMat);imshow("srcMat", srcMat);waitKey(0);destroyAllWindows();}return 0;}