opencv_ex17-圖像放大pyrUp、彩色轉灰階cvtColor、灰階圖像邊緣檢測Sobel(Scharr)、灰階像素點的值at(y, x)、灰階像素運算正規化saturate_cast、單純圖像相加add、圖像相加可定義權重addWeighted
opencv_ex17-圖像放大pyrUp、彩色轉灰階cvtColor、灰階圖像邊緣檢測Sobel(Scharr)、灰階像素點的值at<uchar>(y, x)、灰階像素運算正規化saturate_cast、單純圖像相加add、圖像相加可定義權重addWeighted
GITHUB:https://github.com/jash-git/CPP_opencv249_ex
void Scharr(InputArray src, OutputArray dst, int ddepth, int dx, int dy, double scale=1, double delta=0, int borderType=BORDER_DEFAULT)
或是Sobel(src, dst, ddepth, dx, dy, CV_SCHARR),兩者效果相同。
src:輸入圖。
dst:輸出圖,和輸入圖有相同的尺寸和通道數。
ddepth:輸出圖的深度,使用方式和Sobel相同。
dx:x方向的微分階數。
dy:y方向的微分階數。
scale:縮放值
delta:偏移量。
void Sobel(InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize=3, double scale=1, double delta=0, int borderType=BORDER_DEFAULT)
src:輸入圖。
dst:輸出圖,和輸入圖有相同的尺寸和通道數。
ddepth:輸出圖的深度,假設輸入圖為CV_8U, 支援CV_8U、CV_16S、CV_32F、CV_64F,假設輸入圖為 CV_16U, 支援CV_16U、CV_32F、CV_64F。
dx:x方向的微分階數。
dy:y方向的微分階數。
ksize:核心,必須為1、3、5或7。
scale:縮放值。
delta:偏移量。
計算輸入圖各像素,並將結果轉成8位元圖
void convertScaleAbs(InputArray src, OutputArray dst, double alpha=1, double beta=0)
src:輸入圖。
dst:輸出圖。
alpha:選擇性的乘法因子。
beta:選擇性的加法因子。
此函式主要進行3步驟;1.計算 2.取絕對值 3.轉成無正負號8位元圖
用saturate_cast將每次的計算結果限定在合理範圍,以本例來說就是從0到255,超過255會設定成255,小於0會設定成0。
OpenCV 限定合理範圍:template< … > _Tp saturate_cast(_Tp2 v)
v:輸入參數,會讓此值在合理範圍。
saturate_cast使用模板,所以呼叫時要指定像素深度。
OpenCV影像相加:void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype=-1)
src1:輸入圖。
alpha:src1的權重。
src2:輸入圖,和src1的尺寸和通道數相同。
beta:src2的權重。
gamma:兩圖相加後再增加的值。
dst:輸出圖,輸出矩陣和輸入矩陣有相同的尺寸和通道數。
dtype:可有可無的輸出圖深度。
OpenCV影像相加:void add(InputArray src1, InputArray src2, OutputArray dst, InputArray mask=noArray(), int dtype=-1)
src1 :輸入圖或強度值。
src2 :輸入圖或強度值。
dst:輸出圖,輸出圖和輸入圖有相同的尺寸和通道數。
mask:可有可無的遮罩,8位元單通道圖,指定那些像素要計算。
dtype:可有可無的輸出圖深度。
心得:
01.雖然已經學會利用灰階圖像做Sobel要讓結果清晰可見的訣竅就是要用convertScaleAbs,但是如果實際應用應該還是要把圖轉成二值化資料會更少,也會比較好後續運算
02.Sobel(Scharr)目前測試只能用在灰階圖像,不能用在二值化圖像
03.所以OPENCV的邊緣檢測SOP: 灰階->濾波(高斯)->邊緣檢測->二值化
#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/ml/ml.hpp> #include <iostream> #include <cstdio> #include <sys/timeb.h> #if defined(WIN32) #define TIMEB _timeb #define ftime _ftime typedef __int64 TIME_T; #else #define TIMEB timeb typedef long long TIME_T; #endif using namespace cv; using namespace std; Mat src;//input image void Pause() { printf("Press Enter key to continue..."); fgetc(stdin); } int main() { Mat input,gray_src,dst; input = imread("Lena_original.jpg"); if (!input.data) { printf("could not load image...\n"); } else { //放大 pyrUp(input, src, Size(input.cols*2, input.rows*2)); GaussianBlur(src, dst, Size(3, 3), 0, 0);//高斯模糊GaussianBlur目的為了給圖像預處理時候減低噪聲(雜訊) cvtColor(dst, gray_src, CV_BGR2GRAY);//彩色轉灰階 imshow("Lena_gray", gray_src); Mat Scharr_x, Scharr_y; /* void Scharr(InputArray src, OutputArray dst, int ddepth, int dx, int dy, double scale=1, double delta=0, int borderType=BORDER_DEFAULT) 或是Sobel(src, dst, ddepth, dx, dy, CV_SCHARR),兩者效果相同。 src:輸入圖。 dst:輸出圖,和輸入圖有相同的尺寸和通道數。 ddepth:輸出圖的深度,使用方式和Sobel相同。 dx:x方向的微分階數。 dy:y方向的微分階數。 scale:縮放值 delta:偏移量。 */ Scharr(gray_src, Scharr_x, CV_16S, 1, 0); Scharr(gray_src, Scharr_y, CV_16S, 0, 1); convertScaleAbs(Scharr_x, Scharr_x); convertScaleAbs(Scharr_y, Scharr_y); //--imshow("Scharr_x", Scharr_x); //--imshow("Scharr_y", Scharr_y); /* void Sobel(InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize=3, double scale=1, double delta=0, int borderType=BORDER_DEFAULT) src:輸入圖。 dst:輸出圖,和輸入圖有相同的尺寸和通道數。 ddepth:輸出圖的深度,假設輸入圖為CV_8U, 支援CV_8U、CV_16S、CV_32F、CV_64F,假設輸入圖為 CV_16U, 支援CV_16U、CV_32F、CV_64F。 dx:x方向的微分階數。 dy:y方向的微分階數。 ksize:核心,必須為1、3、5或7。 scale:縮放值。 delta:偏移量。 */ Mat Sobel_x, Sobel_y; Sobel(gray_src, Sobel_x, CV_16S, 1, 0, 3); Sobel(gray_src, Sobel_y, CV_16S, 0, 1, 3); /* 計算輸入圖各像素,並將結果轉成8位元圖 void convertScaleAbs(InputArray src, OutputArray dst, double alpha=1, double beta=0) src:輸入圖。 dst:輸出圖。 alpha:選擇性的乘法因子。 beta:選擇性的加法因子。 此函式主要進行3步驟;1.計算 2.取絕對值 3.轉成無正負號8位元圖 */ convertScaleAbs(Sobel_x, Sobel_x); convertScaleAbs(Sobel_y, Sobel_y); imshow("Sobel_x", Sobel_x); imshow("Sobel_y", Sobel_y); Mat Sobel_xy = Mat(Sobel_x.size(), Sobel_x.type()); int width = Sobel_x.cols; int height = Sobel_y.rows; for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { int xg = Sobel_x.at<uchar>(row, col); int yg = Sobel_y.at<uchar>(row, col); int xy = xg + yg; /* 用saturate_cast將每次的計算結果限定在合理範圍,以本例來說就是從0到255,超過255會設定成255,小於0會設定成0。 OpenCV 限定合理範圍:template< … > _Tp saturate_cast(_Tp2 v) v:輸入參數,會讓此值在合理範圍。 saturate_cast使用模板,所以呼叫時要指定像素深度。 */ Sobel_xy.at<uchar>(row, col) = saturate_cast<uchar>(xy); } } imshow("Sobel_xy", Sobel_xy); Mat Sobel_x_y01 = Mat(Sobel_x.size(), Sobel_x.type()); /* OpenCV影像相加:void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype=-1) src1:輸入圖。 alpha:src1的權重。 src2:輸入圖,和src1的尺寸和通道數相同。 beta:src2的權重。 gamma:兩圖相加後再增加的值。 dst:輸出圖,輸出矩陣和輸入矩陣有相同的尺寸和通道數。 dtype:可有可無的輸出圖深度。 */ addWeighted(Sobel_x, 0.5, Sobel_y, 0.5, 0, Sobel_x_y01);//Sobel_x*0.5+Sobel_y*0.5 imshow("Sobel_x+y01", Sobel_x_y01); Mat Sobel_x_y02 = Mat(Sobel_x.size(), Sobel_x.type());//Sobel_x+Sobel_y /* OpenCV影像相加:void add(InputArray src1, InputArray src2, OutputArray dst, InputArray mask=noArray(), int dtype=-1) src1 :輸入圖或強度值。 src2 :輸入圖或強度值。 dst:輸出圖,輸出圖和輸入圖有相同的尺寸和通道數。 mask:可有可無的遮罩,8位元單通道圖,指定那些像素要計算。 dtype:可有可無的輸出圖深度。 */ add(Sobel_x, Sobel_y, Sobel_x_y02); imshow("Sobel_x+y02", Sobel_x_y02); } waitKey(0); Pause(); return 0; }