├── DOG.cpp ├── LOG.cpp ├── OTSU.cpp ├── OTSU2d.cpp ├── README.md ├── adaptivethreshold.cpp ├── bicubic.cpp ├── bilateralfilter.cpp ├── blackhat.cpp ├── boundingrect.cpp ├── boxfilter.cpp ├── brief.cpp ├── canny.cpp ├── close.cpp ├── copymakeborder.cpp ├── dilate.cpp ├── equalizehistogram.cpp ├── erode.cpp ├── fast.cpp ├── fitline.cpp ├── getconnecteddomain.cpp ├── gradient.cpp ├── gussianfilter.cpp ├── harris.cpp ├── histogram.cpp ├── hough.cpp ├── houghlines.cpp ├── laplacian.cpp ├── linear.cpp ├── maxentropy.cpp ├── medianfilter.cpp ├── modelmatch.cpp ├── nearest.cpp ├── open.cpp ├── orb.cpp ├── prewitt.cpp ├── regiongrow.cpp ├── roberts.cpp ├── shi-tomas.cpp ├── sift.cpp ├── skeleton.cpp ├── sobel.cpp ├── susan.cpp └── tophat.cpp /DOG.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: DOG算子 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | * @param size 掩膜大小 9 | * @param sigma 方差 10 | * @param k 系数 11 | */ 12 | void DOG(cv::Mat& src, cv::Mat& dst, cv::Size size, double sigma, double k = 1.6) 13 | { 14 | cv::Mat gaussian_dst1, gaussian_dst2; 15 | cv::GaussianBlur(src, gaussian_dst1, size, k*sigma); 16 | cv::GaussianBlur(src, gaussian_dst2, size, sigma); 17 | dst = gaussian_dst1 - gaussian_dst2; 18 | cv::threshold(dst, dst, 0, 255, cv::THRESH_BINARY); 19 | } 20 | 21 | int main(int argc, char* argv[]) 22 | { 23 | cv::Mat src = cv::imread("1.jpg", 0), dst; 24 | 25 | DOG(src, dst, cv::Size(13, 13), 1); 26 | cv::imwrite("dog.jpg", dst); 27 | 28 | system("pause"); 29 | return EXIT_SUCCESS; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /LOG.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: LOG算子 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | */ 9 | void LOG(cv::Mat& src, cv::Mat& dst) 10 | { 11 | cv::Mat kernel = (cv::Mat_(5, 5) << 0, 0 ,-1, 0, 0, 0, -1, -2, -1, 0, -1, -2, 16, -2, -1, 0, -1, -2, -1, 0, 0, 0, -1, 0, 0); 12 | cv::filter2D(src, dst, src.depth(), kernel); 13 | } 14 | 15 | int main(int argc, char* argv[]) 16 | { 17 | cv::Mat src = cv::imread("1.jpg", 0), dst; 18 | 19 | LOG(src, dst); 20 | cv::imwrite("log.jpg", dst); 21 | 22 | system("pause"); 23 | return EXIT_SUCCESS; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /OTSU.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 最大类间方差法图像分割 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | */ 9 | void OTSU(cv::Mat& src, cv::Mat& dst) 10 | { 11 | int thresh = 0; 12 | double var = 0.0; 13 | uchar *data = src.data; 14 | int histogram[256] = { 0 }; 15 | int totalnum = src.rows*src.cols; 16 | 17 | for (int i = 0; i < src.rows; ++i) 18 | { 19 | const uchar* ptr = src.ptr(i); 20 | for (int j = 0; j < src.cols; ++j) 21 | { 22 | ++histogram[ptr[j]]; 23 | } 24 | } 25 | 26 | for (int i = 0; i< 256; i++) 27 | { 28 | double w0 = 0.0; 29 | double w1 = 0.0; 30 | double u0 = 0.0; 31 | double u1 = 0.0; 32 | 33 | for (int j = 0; j <= i; j++) 34 | { 35 | w1 += histogram[j]; 36 | u1 += j*histogram[j]; 37 | } 38 | 39 | u1 = (double) u1 / w1; 40 | w1 = (double) w1 / totalnum; 41 | 42 | for (int k = i + 1; k < 256; k++) 43 | { 44 | w0 += histogram[k]; 45 | u0 += k*histogram[k]; 46 | } 47 | 48 | u0 = (double) u0 / w0; 49 | w0 = (double) w0 / totalnum; 50 | 51 | double value = w0*w1*pow(u1 - u0, 2); 52 | if (var < value) 53 | { 54 | var = value; 55 | thresh = i; 56 | } 57 | 58 | } 59 | 60 | dst = src.clone(); 61 | for (int i = 0; i < dst.rows; ++i) 62 | { 63 | uchar* ptr = dst.ptr(i); 64 | for (int j = 0; j < dst.cols; ++j) 65 | { 66 | if (ptr[j] > thresh) 67 | ptr[j] = 255; 68 | else 69 | ptr[j] = 0; 70 | } 71 | } 72 | } 73 | 74 | int main(int argc, char* argv[]) 75 | { 76 | cv::Mat src = cv::imread("1.jpg", 0), dst; 77 | 78 | OTSU(src, dst); 79 | cv::imwrite("otsu.jpg", dst); 80 | 81 | system("pause"); 82 | return EXIT_SUCCESS; 83 | } 84 | 85 | -------------------------------------------------------------------------------- /OTSU2d.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 最大类间方差法(2d)图像分割 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | */ 9 | void OTSU2d(cv::Mat& src, cv::Mat& dst) 10 | { 11 | double histogram[256][256] = { 0.0 }; 12 | double trMatrix = 0.0; 13 | int totalnum = src.rows * src.cols; 14 | 15 | for (int i = 0; i(i, j); 20 | uchar nData2 = 0; 21 | int nData3 = 0; 22 | for (int m = i - 1; m <= i + 1; m++) 23 | { 24 | for (int n = j - 1; n <= j + 1; n++) 25 | { 26 | if ((m>=0) && (m=0) && (n(m, n); 28 | } 29 | } 30 | nData2 = (uchar)(nData3 / 9); 31 | histogram[nData1][nData2]++; 32 | } 33 | } 34 | 35 | for (int i = 0; i < 256; i++) 36 | { 37 | for (int j = 0; j < 256; j++) 38 | { 39 | histogram[i][j] /= totalnum; 40 | } 41 | } 42 | 43 | double p_fi = 0.0; 44 | double p_fj = 0.0; 45 | double p_bi = 0.0; 46 | double p_bj = 0.0; 47 | double p_gi = 0.0; 48 | double p_gj = 0.0; 49 | double w_f = 0.0; 50 | double w_b = 0.0; 51 | double data1 = 0.0; 52 | double data2 = 0.0; 53 | double data3 = 0.0; 54 | double data4 = 0.0; 55 | int threshold_s = 0; 56 | int threshold_t = 0; 57 | double temp = 0.0; 58 | for (int i = 0; i < 256; i++) 59 | { 60 | for (int j = 0; j < 256; j++) 61 | { 62 | p_gi += i*histogram[i][j]; 63 | p_gj += j*histogram[i][j]; 64 | } 65 | } 66 | for (int i = 0; i < 256; i++) 67 | { 68 | for (int j = 0; j < 256; j++) 69 | { 70 | w_f += histogram[i][j]; 71 | data1 += i*histogram[i][j]; 72 | data2 += j*histogram[i][j]; 73 | 74 | w_b = 1 - w_f; 75 | data3 = p_gi - data1; 76 | data4 = p_gj - data2; 77 | 78 | p_fi = data1 / w_f; 79 | p_fj = data2 / w_f; 80 | p_bi = data3 / w_b; 81 | p_bj = data4 / w_b; 82 | trMatrix = ((w_f*p_gi - data1)*(w_f*p_gi - data1) + (w_f*p_gj - data1)*(w_f*p_gj - data2)) / (w_f*w_b); 83 | if (trMatrix > temp) 84 | { 85 | temp = trMatrix; 86 | threshold_s = i; 87 | threshold_t = j; 88 | } 89 | } 90 | } 91 | 92 | int thresh = (threshold_s + threshold_t) / 2; 93 | 94 | dst = src.clone(); 95 | for (int i = 0; i < dst.rows; ++i) 96 | { 97 | uchar* ptr = dst.ptr(i); 98 | for (int j = 0; j < dst.cols; ++j) 99 | { 100 | if (ptr[j] > thresh) 101 | ptr[j] = 255; 102 | else 103 | ptr[j] = 0; 104 | } 105 | } 106 | } 107 | 108 | int main(int argc, char* argv[]) 109 | { 110 | cv::Mat src = cv::imread("1.jpg", 0), dst; 111 | 112 | OTSU2d(src, dst); 113 | cv::imwrite("otsu2d.jpg", dst); 114 | 115 | system("pause"); 116 | return EXIT_SUCCESS; 117 | } 118 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenCV-algorithm 2 | Implementation of some algorithms in OpenCV 3 | -------------------------------------------------------------------------------- /adaptivethreshold.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taifyang/OpenCV-algorithm/8286d35d75823bda634f96ca8d174ceddac80e31/adaptivethreshold.cpp -------------------------------------------------------------------------------- /bicubic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 计算权重 6 | * @param c c就是u和v,横坐标和纵坐标的输出计算方式一样 7 | * @param a 系数 8 | * @return 权重 9 | */ 10 | std::vector getWeight(float c, float a = -1.0) 11 | { 12 | std::vector temp = { 1 + c, c, 1 - c, 2 - c }; 13 | 14 | std::vector weight(4); 15 | weight[0] = a * pow(fabs(temp[0]), 3) - 5 * a * pow(fabs(temp[0]), 2) + 8 * a * fabs(temp[0]) - 4 * a; 16 | weight[1] = (a + 2) * pow(fabs(temp[1]), 3) - (a + 3) * pow(fabs(temp[1]), 2) + 1; 17 | weight[2] = (a + 2) * pow(fabs(temp[2]), 3) - (a + 3) * pow(fabs(temp[2]), 2) + 1; 18 | weight[3] = a * pow(fabs(temp[3]), 3) - 5 * a * pow(fabs(temp[3]), 2) + 8 * a * fabs(temp[3]) - 4 * a; 19 | 20 | return weight; 21 | } 22 | 23 | /** 24 | * @description: 双三次插值 25 | * @param src 输入图像 26 | * @param dst 输出图像 27 | * @param sx x方向缩放系数 28 | * @param sy y方向缩放系数 29 | */ 30 | void bicubic(cv::Mat& src, cv::Mat& dst, float sx, float sy) 31 | { 32 | int dst_cols = sx*src.cols, dst_rows = sy*src.rows; 33 | dst.create(dst_rows, dst_cols, src.type()); 34 | 35 | for (int i = 0; i < dst_rows; ++i) 36 | { 37 | float index_i = (i + 0.5) / sy - 0.5; 38 | if (index_i < 0) index_i = 0; 39 | if (index_i > src.rows - 1) index_i = src.rows - 1; 40 | 41 | int i0 = index_i - 1, i1 = index_i, i2 = index_i + 1, i3 = index_i + 2; 42 | float u = index_i - i1; 43 | std::vector weight_u = getWeight(u); 44 | 45 | for (int j = 0; j < dst_cols; ++j) 46 | { 47 | float index_j = (j + 0.5) / sx - 0.5; 48 | if (index_j < 0) index_j = 0; 49 | if (index_j > src.cols - 1) index_j = src.cols - 1; 50 | 51 | int j0 = index_j - 1, j1 = index_j, j2 = index_j + 1, j3 = index_j + 2; 52 | float v = index_j - j1; 53 | std::vector weight_v = getWeight(v); 54 | 55 | float temp = 0; 56 | for (int s = 0; s <= 3; s++) 57 | { 58 | for (int t = 0; t <= 3; t++) 59 | { 60 | temp += src.at(i1 + s - 1, j1 + t - 1)*weight_u[s] * weight_v[t]; 61 | } 62 | } 63 | 64 | if (temp < 0) temp = 0; 65 | if (temp > 255) temp = 255; 66 | dst.at(i, j) = temp; 67 | } 68 | } 69 | } 70 | 71 | int main(int argc, char* argv[]) 72 | { 73 | cv::Mat src = cv::imread("1.jpg", 0), dst; 74 | 75 | bicubic(src, dst, 2, 2); 76 | cv::imwrite("bicubic.jpg", dst); 77 | 78 | system("pause"); 79 | return EXIT_SUCCESS; 80 | } 81 | 82 | -------------------------------------------------------------------------------- /bilateralfilter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 计算颜色空间 6 | * @param size 掩膜大小 7 | * @param sigmacolor 颜色空间滤波器标准差 8 | * @return 颜色空间 9 | */ 10 | cv::Mat getcolor(int size, double sigmacolor) 11 | { 12 | cv::Mat colormat = cv::Mat::zeros(256, 1, CV_64F); 13 | for (int i = 0; i < 256; ++i) 14 | { 15 | colormat.at(i, 0) = exp((-i*i) / (2.0 * pow(sigmacolor, 2))); 16 | } 17 | return colormat; 18 | } 19 | 20 | /** 21 | * @description: 计算坐标空间 22 | * @param size 掩膜大小 23 | * @param sigmasapce 坐标空间滤波器标准差 24 | * @return 坐标空间 25 | */ 26 | cv::Mat getspace(int size, double sigmasapce) 27 | { 28 | cv::Mat spacemat = cv::Mat::zeros(size, size, CV_64F); 29 | int center_i = (size - 1) / 2, center_j = (size - 1) / 2; 30 | for (int i = 0; i < size; ++i) 31 | { 32 | for (int j = 0; j < size; ++j) 33 | { 34 | spacemat.at(i, j) = exp((-pow(i - center_i, 2) - pow(j - center_j, 2)) / (2.0 * pow(sigmasapce, 2))); 35 | } 36 | } 37 | return spacemat; 38 | } 39 | 40 | /** 41 | * @description: 双边滤波 42 | * @param src 输入图像 43 | * @param dst 输出图像 44 | * @param d 过滤过程中像素邻域直径 45 | * @param sigmacolor 颜色空间滤波器标准差 46 | * @param sigmaspace 坐标空间滤波器标准差 47 | */ 48 | void bilateralfilter(cv::Mat& src, cv::Mat& dst, int d, double sigmacolor, double sigmaspace) 49 | { 50 | dst = cv::Mat::zeros(src.size(),src.type()); 51 | cv::Mat mask = cv::Mat::zeros(d, d, CV_64F); 52 | cv::Mat colormat = getcolor(d, sigmacolor); 53 | cv::Mat spacemat = getspace(d, sigmaspace); 54 | cv::Mat mid; 55 | int b = (d - 1) / 2; 56 | cv::copyMakeBorder(src, mid, b, b, b, b, cv::BORDER_DEFAULT); 57 | 58 | for (int i = b; i < src.rows + b; ++i) 59 | { 60 | for (int j = b; j < src.cols + b; ++j) 61 | { 62 | int graydiff = 0; 63 | double sum = 0.0; 64 | 65 | for (int r = -b; r <= b; ++r) 66 | { 67 | for (int c = -b; c <= b; ++c) 68 | { 69 | graydiff = abs(mid.at(i + r, j + c) - mid.at(i, j)); 70 | mask.at(r + b, c + b) = colormat.at(graydiff, 0) * spacemat.at(r + b, c + b); 71 | sum += mask.at(r + b, c + b); 72 | } 73 | } 74 | 75 | mask /= sum; 76 | double pixel = 0.0; 77 | 78 | for (int r = -b; r <= b; ++r) 79 | { 80 | for (int c = -b; c <= b; ++c) 81 | { 82 | pixel += mid.at(i + r, j + c) * mask.at(r + b, c + b); 83 | } 84 | } 85 | 86 | dst.at(i - b, j - b) = pixel; 87 | } 88 | } 89 | } 90 | 91 | int main(int argc, char* argv[]) 92 | { 93 | cv::Mat src = cv::imread("1.jpg", 0), dst; 94 | 95 | bilateralfilter(src, dst, 13, 13 * 2, 13 / 2); 96 | cv::imwrite("bilateralfilter.jpg", dst); 97 | 98 | system("pause"); 99 | return EXIT_SUCCESS; 100 | } 101 | 102 | -------------------------------------------------------------------------------- /blackhat.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 黑帽运算 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | * @param size 掩膜大小 9 | */ 10 | void blackhat(cv::Mat& src, cv::Mat& dst, cv::Size size) 11 | { 12 | cv::Mat element = getStructuringElement(cv::MORPH_RECT, size); 13 | cv::morphologyEx(src, dst, cv::MORPH_CLOSE, element); 14 | dst = dst - src; 15 | } 16 | 17 | int main(int argc, char* argv[]) 18 | { 19 | cv::Mat src = cv::imread("1.jpg", 0), dst; 20 | 21 | blackhat(src, dst, cv::Size(3, 3)); 22 | cv::imwrite("blackhat.jpg", dst); 23 | 24 | system("pause"); 25 | return EXIT_SUCCESS; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /boundingrect.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 计算外接矩形 6 | * @param img 输入图像 7 | * @return 外接矩形 8 | */ 9 | cv::Rect boundingrect(cv::Mat& img) 10 | { 11 | cv::Rect rect(0, 0, 0, 0); 12 | 13 | bool flag = false; 14 | for (size_t i = 0; i < img.cols; ++i) 15 | { 16 | for (size_t j = 0; j < img.rows; ++j) 17 | { 18 | if (img.at(j, i)) 19 | { 20 | rect.x = i; 21 | flag = true; 22 | break; 23 | } 24 | } 25 | if (flag) break; 26 | } 27 | 28 | flag = false; 29 | for (size_t i = img.cols - 1; i > 0; --i) 30 | { 31 | for (size_t j = 0; j < img.rows; ++j) 32 | { 33 | if (img.at(j, i)) 34 | { 35 | rect.width = i - rect.x; 36 | flag = true; 37 | break; 38 | } 39 | } 40 | if (flag) break; 41 | } 42 | 43 | flag = false; 44 | for (size_t i = 0; i < img.rows; ++i) 45 | { 46 | for (size_t j = 0; j < img.cols; ++j) 47 | { 48 | if (img.at(i, j)) 49 | { 50 | rect.y = i; 51 | flag = true; 52 | break; 53 | } 54 | } 55 | if (flag) break; 56 | } 57 | 58 | flag = false; 59 | for (size_t i = img.rows - 1; i >= 0; --i) 60 | { 61 | for (size_t j = 0; j < img.cols; ++j) 62 | { 63 | if (img.at(i, j)) 64 | { 65 | rect.height = i - rect.y; 66 | flag = true; 67 | break; 68 | } 69 | } 70 | if (flag) break; 71 | } 72 | return rect; 73 | } 74 | 75 | int main(int argc, char* argv[]) 76 | { 77 | cv::Mat src = cv::imread("1.jpg", 0), dst; 78 | 79 | cv::Rect rect = boundingrect(src); 80 | std::cout << rect << std::endl; 81 | 82 | system("pause"); 83 | return EXIT_SUCCESS; 84 | } 85 | 86 | -------------------------------------------------------------------------------- /boxfilter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 计算积分图 6 | * @param img 输入图像 7 | * @param sum 积分图 8 | */ 9 | void sumRegion(cv::Mat& img, cv::Mat& sum) 10 | { 11 | for (size_t i = 1; i < sum.rows; i++) 12 | { 13 | for (size_t j = 1; j < sum.cols; j++) 14 | { 15 | sum.at(i, j) = sum.at(i - 1, j) + sum.at(i, j - 1) - sum.at(i - 1, j - 1) + img.at(i - 1, j - 1); 16 | } 17 | } 18 | } 19 | 20 | /** 21 | * @description: 计算区域和 22 | * @param sum 积分图 23 | * @param row1 24 | * @param col1 25 | * @param row2 26 | * @param col2 27 | * @return 区域和 28 | */ 29 | int calcRegion(cv::Mat& sum, int row1, int col1, int row2, int col2) 30 | { 31 | return sum.at(row2 + 1, col2 + 1) - sum.at(row1, col2 + 1) - sum.at(row2 + 1, col1) + sum.at(row1, col1); 32 | } 33 | 34 | /** 35 | * @description: 方框滤波 36 | * @param src 输入图像 37 | * @param dst 输出图像 38 | * @param size 掩膜大小 39 | */ 40 | void boxfilter(cv::Mat& src, cv::Mat& dst, cv::Size size) 41 | { 42 | dst = cv::Mat::zeros(src.rows, src.cols, src.type()); 43 | int w = (size.width - 1) / 2, h = (size.height - 1) / 2; 44 | cv::Mat mid; 45 | cv::copyMakeBorder(src, mid, h, h, w, w, cv::BORDER_DEFAULT); 46 | cv::Mat sum = cv::Mat::zeros(mid.rows + 1, mid.cols + 1, CV_64F); 47 | sumRegion(mid, sum); 48 | 49 | for (size_t i = h ; i < src.rows + h ; i++) 50 | { 51 | for (size_t j = w ; j < src.cols + w ; j++) 52 | { 53 | dst.at(i - h , j - w) = calcRegion(sum, i - h, j - w, i + h, j + w) / (size.width*size.height); 54 | } 55 | } 56 | } 57 | 58 | ///** 59 | // * @description: 方框滤波 60 | // * @param src 输入图像 61 | // * @param dst 输出图像 62 | // * @param size 掩膜大小 63 | // */ 64 | //void boxfilter(cv::Mat& src, cv::Mat& dst, cv::Size size) 65 | //{ 66 | // cv::Mat kernel = cv::Mat::zeros(size, CV_64F); 67 | // for (int i = 0; i < size.height; ++i) 68 | // { 69 | // for (int j = 0; j < size.width; ++j) 70 | // { 71 | // kernel.at(i, j) = 1.0 / (size.height*size.width); 72 | // } 73 | // } 74 | // cv::filter2D(src, dst, src.depth(), kernel); 75 | //} 76 | 77 | int main(int argc, char* argv[]) 78 | { 79 | cv::Mat src = cv::imread("1.jpg", 0), dst; 80 | 81 | boxfilter(src, dst, cv::Size(3, 3)); 82 | cv::imwrite("boxfilter.jpg", dst); 83 | 84 | system("pause"); 85 | return EXIT_SUCCESS; 86 | } 87 | 88 | -------------------------------------------------------------------------------- /brief.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int PATCH_SIZE = 48; 5 | int KERNEL_SIZE = 9; 6 | 7 | 8 | int smoothedSum(const cv::Mat& sum, const cv::KeyPoint& pt, int y, int x, bool use_orientation, cv::Matx21f R) 9 | { 10 | const int HALF_KERNEL = KERNEL_SIZE / 2; 11 | 12 | if (use_orientation) 13 | { 14 | int rx = (int)(((float)x) * R(1, 0) - ((float)y) * R(0, 0)); 15 | int ry = (int)(((float)x) * R(0, 0) + ((float)y) * R(1, 0)); 16 | if (rx > 24) rx = 24; 17 | if (rx < -24) rx = -24; 18 | if (ry > 24) ry = 24; 19 | if (ry < -24) ry = -24; 20 | x = rx; y = ry; 21 | } 22 | const int img_y = (int)(pt.pt.y + 0.5) + y; 23 | const int img_x = (int)(pt.pt.x + 0.5) + x; 24 | return sum.at(img_y + HALF_KERNEL + 1, img_x + HALF_KERNEL + 1) 25 | - sum.at(img_y + HALF_KERNEL + 1, img_x - HALF_KERNEL) 26 | - sum.at(img_y - HALF_KERNEL, img_x + HALF_KERNEL + 1) 27 | + sum.at(img_y - HALF_KERNEL, img_x - HALF_KERNEL); 28 | } 29 | 30 | void pixelTests32(cv::Mat sum, std::vector keypoints, cv::Mat descriptors, bool use_orientation) 31 | { 32 | cv::Matx21f R; 33 | for (size_t i = 0; i < keypoints.size(); ++i) 34 | { 35 | uchar* desc = descriptors.ptr(static_cast(i)); 36 | cv::KeyPoint pt = keypoints[i]; 37 | if (use_orientation) 38 | { 39 | float angle = pt.angle; 40 | angle *= (float)(CV_PI / 180.f); 41 | R(0, 0) = sin(angle); 42 | R(1, 0) = cos(angle); 43 | } 44 | 45 | #include "generated_32.i" 46 | } 47 | } 48 | 49 | 50 | void my_brief_des(cv::Mat image, std::vector keypoints, int bytes = 32, bool use_orientation = false) 51 | { 52 | cv::Mat sum; 53 | cv::integral(image, sum, CV_32S); 54 | cv::KeyPointsFilter::runByImageBorder(keypoints, image.size(), PATCH_SIZE / 2 + KERNEL_SIZE / 2); 55 | 56 | cv::Mat descriptors; 57 | descriptors.create((int)keypoints.size(), bytes, CV_8U); 58 | descriptors.setTo(cv::Scalar::all(0)); 59 | 60 | pixelTests32(sum, keypoints, descriptors, use_orientation); 61 | std::cout << descriptors << std::endl; 62 | } 63 | 64 | 65 | int main() 66 | { 67 | cv::Mat img = cv::imread("susan_input1.png", 0); 68 | cv::Ptr fast = cv::FastFeatureDetector::create(); 69 | std::vector keypoints; 70 | fast->detect(img, keypoints); 71 | 72 | my_brief_des(img, keypoints); 73 | 74 | return 0; 75 | } -------------------------------------------------------------------------------- /canny.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 计算阶乘 6 | * @param n 自然数 7 | * @return 阶乘 8 | */ 9 | int factorial(int n) 10 | { 11 | int fac = 1; 12 | if (n == 0) return fac; 13 | for (int i = 1; i <= n; ++i) fac *= i; 14 | return fac; 15 | } 16 | 17 | /** 18 | * @description: 获得Sobel平滑算子 19 | * @param size 掩膜大小 20 | * @return Sobel平滑算子 21 | */ 22 | cv::Mat getSobelSmooth(int size) 23 | { 24 | int n = size - 1; 25 | cv::Mat SobelSmoothoper = cv::Mat::zeros(size, 1, CV_32F); 26 | for (int k = 0; k <= n; k++) 27 | { 28 | float *pt = SobelSmoothoper.ptr(0); 29 | pt[k] = factorial(n) / (factorial(k)*factorial(n - k)); 30 | } 31 | return SobelSmoothoper; 32 | } 33 | 34 | /** 35 | * @description: 获得Sobel差分算子 36 | * @param size 掩膜大小 37 | * @return Sobel差分算子 38 | */ 39 | cv::Mat getSobeldiff(int size) 40 | { 41 | cv::Mat Sobeldiffoper = cv::Mat::zeros(cv::Size(size, 1), CV_32F); 42 | cv::Mat SobelSmooth = getSobelSmooth(size - 1); 43 | for (int k = 0; k < size; k++) 44 | { 45 | if (k == 0) 46 | Sobeldiffoper.at(0, k) = 1; 47 | else if (k == size - 1) 48 | Sobeldiffoper.at(0, k) = -1; 49 | else 50 | Sobeldiffoper.at(0, k) = SobelSmooth.at(0, k) - SobelSmooth.at(0, k - 1); 51 | } 52 | return Sobeldiffoper; 53 | } 54 | 55 | /** 56 | * @description: 卷积实现 57 | * @param src 输入图像 58 | * @param dst 输出图像 59 | * @param kernel 卷积核 60 | */ 61 | void conv2D(cv::Mat& src, cv::Mat& dst, cv::Mat kernel) 62 | { 63 | cv::flip(kernel, kernel, -1); 64 | cv::filter2D(src, dst, CV_32F, kernel); 65 | } 66 | 67 | /** 68 | * @description: 可分离卷积———先水平方向卷积,后垂直方向卷积 69 | * @param src 输入图像 70 | * @param dst 输出图像 71 | * @param kernel_X x方向卷积 72 | * @param kernel_Y y方向卷积 73 | */ 74 | void sepConv2D_X_Y(cv::Mat& src, cv::Mat& dst, cv::Mat kernel_X, cv::Mat kernel_Y) 75 | { 76 | cv::Mat dst_kernel_X; 77 | conv2D(src, dst_kernel_X, kernel_X); 78 | conv2D(dst_kernel_X, dst, kernel_Y); 79 | } 80 | 81 | /** 82 | * @description: 可分离卷积———先垂直方向卷积,后水平方向卷积 83 | * @param src 输入图像 84 | * @param dst 输出图像 85 | * @param kernel_Y y方向卷积 86 | * @param kernel_X x方向卷积 87 | */ 88 | void sepConv2D_Y_X(cv::Mat& src, cv::Mat& dst, cv::Mat kernel_Y, cv::Mat kernel_X) 89 | { 90 | cv::Mat dst_kernel_Y; 91 | conv2D(src, dst_kernel_Y, kernel_Y); 92 | conv2D(dst_kernel_Y, dst, kernel_X); 93 | } 94 | 95 | /** 96 | * @description: Sobel算子边缘检测 97 | * @param src 输入图像 98 | * @param dst 输出图像 99 | * @param dst_X x方向边缘 100 | * @param dst_Y y方向边缘 101 | * @param size 掩膜大小 102 | */ 103 | void sobel(cv::Mat& src, cv::Mat& dst, cv::Mat& dst_X, cv::Mat& dst_Y, int size) 104 | { 105 | cv::Mat SobelSmoothoper = getSobelSmooth(size); 106 | cv::Mat Sobeldiffoper = getSobeldiff(size); 107 | 108 | sepConv2D_X_Y(src, dst_Y, SobelSmoothoper, Sobeldiffoper.t()); 109 | sepConv2D_Y_X(src, dst_X, SobelSmoothoper.t(), Sobeldiffoper); 110 | 111 | dst = abs(dst_X) + abs(dst_Y); 112 | convertScaleAbs(dst, dst); 113 | } 114 | 115 | /** 116 | * @description: 确定一个点的坐标是否在图像内 117 | * @param r 点的行坐标 118 | * @param c 点的列坐标 119 | * @param rows 图像行数 120 | * @param cols 图像列数 121 | * @return 点的坐标是否在图像内 122 | */ 123 | bool checkInRange(int r, int c, int rows, int cols) 124 | { 125 | if (r >= 0 && r < rows && c >= 0 && c < cols) 126 | return true; 127 | else 128 | return false; 129 | } 130 | 131 | /** 132 | * @description: 从确定边缘点出发,延长边缘 133 | * @param edgeMag_noMaxsup 未经过极大值抑制的边缘强度 134 | * @param edge 图像边缘 135 | * @param Th 灰度阈值 136 | * @param r 点的行坐标 137 | * @param c 点的列坐标 138 | * @param rows 图像行数 139 | * @param cols 图像列数 140 | */ 141 | void trace(cv::Mat &edgeMag_noMaxsup, cv::Mat &edge, float Th, int r, int c, int rows, int cols) 142 | { 143 | if (edge.at(r, c) == 0) 144 | { 145 | for (int i = -1; i <= 1; ++i) 146 | { 147 | for (int j = -1; j <= 1; ++j) 148 | { 149 | if (checkInRange(r + i, c + j, rows, cols) && edgeMag_noMaxsup.at(r + i, c + j) > Th) 150 | edge.at(r, c) = 255; 151 | } 152 | } 153 | } 154 | } 155 | 156 | /** 157 | * @description: Canny边缘检测 158 | * @param src 输入图像 159 | * @param dst 输出图像 160 | * @param Tl 低灰度阈值 161 | * @param Th 高灰度阈值 162 | * @param ksize sobel算子掩膜大小 163 | * @param L2graydient 是否使用L2灰度梯度 164 | */ 165 | void canny(cv::Mat &src, cv::Mat &dst, float Tl, float Th, int ksize = 3, bool L2graydient = false) 166 | { 167 | cv::GaussianBlur(src, src, cv::Size(3, 3), 0); 168 | cv::Mat dx, dy, sobel_dst; 169 | sobel(src, sobel_dst, dx, dy, ksize); 170 | 171 | cv::Mat edgeMag; 172 | if (L2graydient) 173 | magnitude(dx, dy, edgeMag); 174 | else 175 | edgeMag = abs(dx) + abs(dy); 176 | 177 | cv::Mat edgeMag_noMaxsup = cv::Mat::zeros(src.size(), CV_32F); 178 | for (int i = 1; i < src.rows - 1; ++i) 179 | { 180 | for (int j = 1; j < src.cols - 1; ++j) 181 | { 182 | float angle = atan2f(dy.at(i, j), dx.at(i, j)) / CV_PI * 180; 183 | float cur = edgeMag.at(i, j); 184 | 185 | if (abs(angle) < 22.5 || abs(angle) > 157.5) 186 | { 187 | float left = edgeMag.at(i, j - 1); 188 | float right = edgeMag.at(i, j + 1); 189 | if (cur >= left && cur >= right) 190 | edgeMag_noMaxsup.at(i, j) = cur; 191 | } 192 | 193 | if ((angle >= 67.5 && angle <= 112.5) || (angle >= -112.5 && angle <= -67.5)) 194 | { 195 | float top = edgeMag.at(i - 1, j); 196 | float down = edgeMag.at(i + 1, j); 197 | if (cur >= top && cur >= down) 198 | edgeMag_noMaxsup.at(i, j) = cur; 199 | } 200 | 201 | if ((angle>112.5 && angle <= 157.5) || (angle>-67.5 && angle <= -22.5)) 202 | { 203 | float right_top = edgeMag.at(i - 1, j + 1); 204 | float left_down = edgeMag.at(i + 1, j - 1); 205 | if (cur >= right_top && cur >= left_down) 206 | edgeMag_noMaxsup.at(i, j) = cur; 207 | } 208 | 209 | if ((angle >= 22.5 && angle < 67.5) || (angle >= -157.5 && angle < -112.5)) 210 | { 211 | float left_top = edgeMag.at(i - 1, j - 1); 212 | float right_down = edgeMag.at(i + 1, j + 1); 213 | if (cur >= left_top && cur >= right_down) 214 | edgeMag_noMaxsup.at(i, j) = cur; 215 | } 216 | 217 | } 218 | } 219 | 220 | dst = cv::Mat::zeros(src.size(), CV_8U); 221 | for (int i = 1; i < src.rows - 1; ++i) 222 | { 223 | for (int j = 1; j < src.cols - 1; ++j) 224 | { 225 | float mag = edgeMag_noMaxsup.at(i, j); 226 | if (mag > Th) 227 | dst.at(i, j) = 255; 228 | else if (mag < Tl) 229 | dst.at(i, j) = 0; 230 | else 231 | trace(edgeMag_noMaxsup, dst, Th, i, j, src.rows, src.cols); 232 | } 233 | } 234 | } 235 | 236 | int main(int argc, char* argv[]) 237 | { 238 | cv::Mat src = cv::imread("1.jpg", 0), dst; 239 | 240 | canny(src, dst, 20, 60); 241 | cv::imwrite("canny.jpg", dst); 242 | 243 | system("pause"); 244 | return EXIT_SUCCESS; 245 | } 246 | 247 | -------------------------------------------------------------------------------- /close.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 闭运算 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | * @param size 掩膜大小 9 | */ 10 | void close(cv::Mat& src, cv::Mat& dst, cv::Size size) 11 | { 12 | cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, size); 13 | cv::dilate(src, dst, element); 14 | cv::erode(dst, dst, element); 15 | } 16 | 17 | int main(int argc, char* argv[]) 18 | { 19 | cv::Mat src = cv::imread("1.jpg", 0), dst; 20 | 21 | close(src, dst, cv::Size(3, 3)); 22 | imwrite("close.jpg", dst); 23 | 24 | system("pause"); 25 | return EXIT_SUCCESS; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /copymakeborder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 边界复制 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | * @param top 图像上沿 9 | * @param bottom 图像下沿 10 | * @param left 图像左沿 11 | * @param right 图像右沿 12 | */ 13 | void copymakeborder(cv::Mat& src, cv::Mat& dst, int top, int bottom, int left, int right) 14 | { 15 | dst = cv::Mat::zeros(src.rows + top + bottom, src.cols + left + right, src.type()); 16 | for (int i = top; i < src.rows + top; ++i) 17 | { 18 | for (int j = left; j < src.cols + left; ++j) 19 | { 20 | dst.at(i, j) = src.at(i - top, j - left); 21 | } 22 | } 23 | for (int i = top; i < src.rows + top; ++i) 24 | { 25 | for (int j = 0; j < left; ++j) 26 | { 27 | dst.at(i, j) = dst.at(i, 2 * left - j); 28 | } 29 | } 30 | for (int i = top; i < src.rows + top; ++i) 31 | { 32 | for (int j = src.cols + left; j < src.cols + left + right; ++j) 33 | { 34 | dst.at(i, j) = dst.at(i, 2 * (src.cols + left - 1) - j); 35 | } 36 | } 37 | for (int i = 0; i < top; ++i) 38 | { 39 | for (int j = 0; j < src.cols + left + right; ++j) 40 | { 41 | dst.at(i, j) = dst.at(2 * top - i, j); 42 | } 43 | } 44 | for (int i = src.rows; i < src.rows + top; ++i) 45 | { 46 | for (int j = 0; j < src.cols + left + right; ++j) 47 | { 48 | dst.at(i, j) = dst.at(2 * (src.rows + top - 1) - i, j); 49 | } 50 | } 51 | } 52 | 53 | int main(int argc, char* argv[]) 54 | { 55 | cv::Mat src = cv::imread("1.jpg", 0), dst; 56 | 57 | copymakeborder(src, dst, 6, 6, 6, 6); 58 | cv::imwrite("copymakeborder.jpg", dst); 59 | 60 | system("pause"); 61 | return EXIT_SUCCESS; 62 | } 63 | 64 | -------------------------------------------------------------------------------- /dilate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 膨胀运算 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | * @param size 掩膜大小 9 | */ 10 | void dilate(cv::Mat& src, cv::Mat& dst, cv::Size size) 11 | { 12 | dst = cv::Mat::zeros(src.size(), src.type()); 13 | cv::Mat mid; 14 | int h = (size.height - 1) / 2, w = (size.width - 1) / 2; 15 | cv::copyMakeBorder(src, mid, h, h, w, w, cv::BORDER_DEFAULT); 16 | for (int i = h; i < src.rows + h; ++i) 17 | { 18 | for (int j = w; j < src.cols + w; ++j) 19 | { 20 | cv::Mat kernel = mid(cv::Rect(j - w, i - h, size.width, size.height)); 21 | double minValue, maxValue; 22 | cv::Point minIdx, maxIdx; 23 | cv::minMaxLoc(kernel, &minValue, &maxValue, &minIdx, &maxIdx); 24 | dst.at(i - h, j - w) = maxValue; 25 | } 26 | } 27 | } 28 | 29 | int main(int argc, char* argv[]) 30 | { 31 | cv::Mat src = cv::imread("1.jpg", 0), dst; 32 | 33 | dilate(src, dst, cv::Size(13, 13)); 34 | cv::imwrite("dilate.jpg", dst); 35 | 36 | system("pause"); 37 | return EXIT_SUCCESS; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /equalizehistogram.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 直方图均衡化 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | */ 9 | void equalizehist(cv::Mat &src, cv::Mat &dst) 10 | { 11 | dst.create(src.size(), src.type()); 12 | 13 | int histogram[256] = { 0 }; 14 | int totalnum = src.rows*src.cols; 15 | uchar *data = src.data; 16 | for (int i = 0; i < totalnum; ++i) 17 | { 18 | ++histogram[data[i]]; 19 | } 20 | 21 | int LUT[256], sum = 0; 22 | for (int i = 0; i < 256; ++i) 23 | { 24 | sum += histogram[i]; 25 | LUT[i] = 255.0*sum / totalnum; 26 | } 27 | 28 | uchar *dataOfSrc = src.data; 29 | uchar *dataOfDst = dst.data; 30 | for (int i = 0; i < totalnum; ++i) 31 | dataOfDst[i] = LUT[dataOfSrc[i]]; 32 | } 33 | 34 | int main(int argc, char* argv[]) 35 | { 36 | cv::Mat src = cv::imread("1.jpg", 0), dst; 37 | 38 | equalizehist(src, dst); 39 | cv::imwrite("equalizehist.jpg", dst); 40 | 41 | system("pause"); 42 | return EXIT_SUCCESS; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /erode.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 腐蚀运算 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | * @param size 掩膜大小 9 | */ 10 | void erode(cv::Mat& src, cv::Mat& dst, cv::Size size) 11 | { 12 | dst = cv::Mat::zeros(src.size(), src.type()); 13 | cv::Mat mid; 14 | int h = (size.height - 1) / 2, w = (size.width - 1) / 2; 15 | cv::copyMakeBorder(src, mid, h, h, w, w, cv::BORDER_DEFAULT); 16 | for (int i = h; i < src.rows + h; ++i) 17 | { 18 | for (int j = w; j < src.cols + w; ++j) 19 | { 20 | cv::Mat kernel = mid(cv::Rect(j - w, i - h, size.width, size.height)); 21 | double minValue, maxValue; 22 | cv::Point minIdx, maxIdx; 23 | cv::minMaxLoc(kernel, &minValue, &maxValue, &minIdx, &maxIdx); 24 | dst.at(i - h, j - w) = minValue; 25 | } 26 | } 27 | } 28 | 29 | int main(int argc, char* argv[]) 30 | { 31 | cv::Mat src = cv::imread("1.jpg", 0), dst; 32 | 33 | erode(src, dst, cv::Size(3, 3)); 34 | cv::imwrite("erode.jpg", dst); 35 | 36 | system("pause"); 37 | return EXIT_SUCCESS; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /fast.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | void fast(cv::Mat& src, cv::Mat& dst, int t = 10) 6 | { 7 | int fast_N = 9; 8 | int detect_radius = 3; 9 | std::vector row_mask = { 0,0,1,2,3,4,5,6,6,6,5,4,3,2,1,0 }; 10 | std::vector col_mask = { 3,4,5,6,6,6,5,4,3,2,1,0,0,0,1,2 }; 11 | 12 | cv::Mat score_arr = cv::Mat::zeros(src.size(), CV_32F); 13 | dst = src.clone(); 14 | cv::cvtColor(dst, dst, cv::COLOR_GRAY2BGR); 15 | int row_s = detect_radius, col_s = detect_radius; 16 | int row_e = src.rows - detect_radius, col_e = src.cols - detect_radius; 17 | 18 | for (size_t i = row_s; i < row_e; i++) 19 | { 20 | for (size_t j = col_s; j < col_e; j++) 21 | { 22 | cv::Mat fast_zone = src(cv::Rect(j - detect_radius, i - detect_radius, 2 * detect_radius + 1, 2 * detect_radius + 1)); 23 | //for (size_t i = 0; i < fast_zone.rows; i++) 24 | //{ 25 | // for (size_t j = 0; j < fast_zone.cols; j++) 26 | // { 27 | // std::cout << (int)fast_zone.at(i, j) << " "; 28 | // } 29 | // std::cout << std::endl; 30 | //} 31 | 32 | int r0 = (int)src.at(i, j); 33 | std::vector condition1(row_mask.size()), condition2(row_mask.size()); 34 | float sum1=0.0, sum2=0.0; 35 | for (size_t k = 0; k < row_mask.size(); k++) 36 | { 37 | if ((int)fast_zone.at(row_mask[k], col_mask[k]) - r0 > t) 38 | { 39 | condition1[k] = 1; 40 | sum1 += (int)fast_zone.at(row_mask[k], col_mask[k]) - r0; 41 | } 42 | if ((int)fast_zone.at(row_mask[k], col_mask[k]) - r0 < -t) 43 | { 44 | condition2[k] = 1; 45 | sum2 += r0 - (int)fast_zone.at(row_mask[k], col_mask[k]); 46 | } 47 | } 48 | 49 | if (condition1[0] + condition1[8] >= 1 && condition1[4] + condition1[12] >= 1) 50 | { 51 | std::vector temp = condition1; 52 | temp.insert(temp.end(), condition1.begin(), condition1.end() - 1); 53 | int len = 0, max_len = 0; 54 | for (size_t k = 0; k < temp.size(); k++) 55 | { 56 | if (temp[k]) 57 | len += 1; 58 | else 59 | len = 0; 60 | max_len = std::max(max_len, len); 61 | } 62 | if (max_len >= fast_N) 63 | { 64 | dst.at(i, j) = cv::Vec3b(0, 0, 255); 65 | score_arr.at(i, j) = sum1; 66 | } 67 | } 68 | if (condition2[0] + condition2[8] >= 1 && condition2[4] + condition2[12] >= 1) 69 | { 70 | std::vector temp = condition2; 71 | temp.insert(temp.end(), condition2.begin(), condition2.end() - 1); 72 | int len = 0, max_len = 0; 73 | for (size_t k = 0; k < temp.size(); k++) 74 | { 75 | if (temp[k]) 76 | len += 1; 77 | else 78 | len = 0; 79 | max_len = std::max(max_len, len); 80 | } 81 | if (max_len >= fast_N) 82 | { 83 | dst.at(i, j) = cv::Vec3b(0, 0, 255); 84 | score_arr.at(i, j) = sum2; 85 | } 86 | } 87 | 88 | } 89 | } 90 | 91 | 92 | #ifdef NMS 93 | for (size_t i = row_s; i < row_e; i++) 94 | { 95 | for (size_t j = col_s; j < col_e; j++) 96 | { 97 | if (dst.at(i, j) != cv::Vec3b(0, 0, 255)) 98 | continue; 99 | cv::Mat zone = score_arr(cv::Rect(j - detect_radius / 2, i - detect_radius / 2, detect_radius + 1, detect_radius + 1)); 100 | int num = 0; 101 | for (size_t m = 0; m < zone.rows; m++) 102 | { 103 | for (size_t n = 0; n < zone.cols; n++) 104 | { 105 | if (zone.at(m, n) > score_arr.at(i, j)) 106 | num++; 107 | } 108 | } 109 | if (num > 0) 110 | { 111 | dst.at(i, j)[0] = src.at(i, j); 112 | dst.at(i, j)[1] = src.at(i, j); 113 | dst.at(i, j)[2] = src.at(i, j); 114 | } 115 | 116 | } 117 | } 118 | #endif // NMS 119 | 120 | } 121 | 122 | 123 | int main(int argc, char** argv) 124 | { 125 | cv::Mat src = cv::imread("1.png", 0), dst; 126 | 127 | fast(src, dst, 10); 128 | cv::imwrite("myfast.png", dst); 129 | 130 | system("pause"); 131 | return EXIT_SUCCESS; 132 | } -------------------------------------------------------------------------------- /fitline.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 直线拟合 6 | * @param points 输入点集 7 | * @param line_para 直线参数 8 | */ 9 | void fitline(std::vector& points, cv::Vec4f& line_para) 10 | { 11 | int N = points.size(); 12 | if (N < 2) return; 13 | 14 | double sum_x = 0, sum_y = 0, sum_xx = 0, sum_xy = 0, sum_yy = 0; 15 | for (int i = 0; i < N; i++) 16 | { 17 | sum_x += points[i].x; 18 | sum_y += points[i].y; 19 | sum_xx += points[i].x * points[i].x; 20 | sum_xy += points[i].x * points[i].y; 21 | sum_yy += points[i].y * points[i].y; 22 | } 23 | 24 | float k = (N*sum_xy-sum_x*sum_y) / (N*sum_xx - sum_x*sum_x); 25 | float b = (sum_xx*sum_y - sum_x*sum_xy) / (N*sum_xx - sum_x*sum_x); 26 | std::cout << "k = " << k << ", b = " << b << std::endl; 27 | 28 | float A, B, C; 29 | float mean_x = sum_x / N, mean_y = sum_y / N, mean_xx = sum_xx / N, mean_xy = sum_xy / N, mean_yy = sum_yy / N; 30 | cv::Mat m = (cv::Mat_(2, 2) << mean_xx - mean_x*mean_x, mean_xy - mean_x*mean_y, mean_xy - mean_x*mean_y, mean_yy - mean_y*mean_y); 31 | 32 | cv::Mat eigenvalue, eigenvector; 33 | cv::eigen(m * N, eigenvalue, eigenvector); 34 | 35 | float v0 = eigenvalue.at(0, 0), v1 = eigenvalue.at(0, 1); 36 | if (abs(v0) < abs(v1)) 37 | { 38 | A = eigenvector.at(0, 0); 39 | B = eigenvector.at(0, 1); 40 | } 41 | else { 42 | A = eigenvector.at(1, 0); 43 | B = eigenvector.at(1, 1); 44 | } 45 | C = -(A*mean_x + B*mean_y); 46 | std::cout << "k = " << -A / B << ", b = " << -C / B << std::endl; 47 | 48 | line_para[0] = B; 49 | line_para[1] = -A; 50 | line_para[2] = mean_x; 51 | line_para[3] = mean_y; 52 | } 53 | 54 | int main(int argc, char* argv[]) 55 | { 56 | std::vector points; 57 | points.push_back(cv::Point(48, 58)); 58 | points.push_back(cv::Point(105, 98)); 59 | points.push_back(cv::Point(155, 160)); 60 | points.push_back(cv::Point(212, 220)); 61 | points.push_back(cv::Point(248, 260)); 62 | points.push_back(cv::Point(320, 300)); 63 | points.push_back(cv::Point(350, 360)); 64 | points.push_back(cv::Point(412, 400)); 65 | 66 | cv::Vec4f line_para; 67 | fitline(points, line_para); 68 | std::cout << "line_para = " << line_para << std::endl; 69 | 70 | system("pause"); 71 | return EXIT_SUCCESS; 72 | } 73 | 74 | -------------------------------------------------------------------------------- /getconnecteddomain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // /** 5 | // * @description: 深度优先搜索 6 | // * @param src 输入图像 7 | // * @param dst 输出图像 8 | // * @param i 行号 9 | // * @param j 列号 10 | // * @param num 区域序号 11 | // */ 12 | // void dfs(cv::Mat& src, cv::Mat& dst, int i, int j, int num) 13 | // { 14 | // if (i >= 0 && i < src.rows && j >= 0 && j < src.cols && src.at(i, j) && dst.at(i, j) == cv::Vec3b(0, 0, 0)) 15 | // { 16 | // dst.at(i, j) = cv::Vec3b(num * 80, 255 - num * 80, 0); 17 | // dfs(src, dst, i - 1, j, num); 18 | // dfs(src, dst, i + 1, j, num); 19 | // dfs(src, dst, i, j - 1, num); 20 | // dfs(src, dst, i, j + 1, num); 21 | // } 22 | // } 23 | 24 | // void getconnecteddomain(cv::Mat& src, cv::Mat &dst) 25 | // { 26 | // dst = cv::Mat::zeros(src.size(), CV_8UC3); 27 | // int num = 0; 28 | 29 | // for (int i = 0; i < src.rows; ++i) 30 | // { 31 | // for (int j = 0; j < src.cols; ++j) 32 | // { 33 | // if (src.at(i, j)!=0 && dst.at(i, j) == cv::Vec3b(0, 0, 0)) 34 | // { 35 | // dfs(src, dst, i, j, num); 36 | // ++num; 37 | // } 38 | // } 39 | // } 40 | // } 41 | 42 | /** 43 | * @description: 连通域标记 44 | * @param src 输入图像 45 | * @param dst 输出图像 46 | */ 47 | void getconnecteddomain(cv::Mat& src, cv::Mat &dst) 48 | { 49 | dst = cv::Mat::zeros(src.size(), CV_8UC3); 50 | int num = 0; 51 | 52 | for (int i = 0; i < src.rows; ++i) 53 | { 54 | for (int j = 0; j < src.cols; ++j) 55 | { 56 | int dir[4][2] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 }}; 57 | std::vector pts; 58 | cv::Point pt,p; 59 | 60 | if (src.at(i, j)!=0 && dst.at(i, j) == cv::Vec3b(0, 0, 0)) 61 | { 62 | pts.push_back(cv::Point(j, i)); 63 | dst.at(i, j) = cv::Vec3b(num * 80, 255 - num * 80, 0); 64 | 65 | while (!pts.empty()) 66 | { 67 | pt = pts.back(); 68 | pts.pop_back(); 69 | 70 | for (int k = 0; k < 4; ++k) 71 | { 72 | p.x = pt.x + dir[k][0]; 73 | p.y = pt.y + dir[k][1]; 74 | 75 | if (p.x < 0 || p.y < 0 || p.x >= src.cols || p.y >= src.rows) continue; 76 | if (src.at(p.y,p.x)!=0 && dst.at(p.y, p.x) == cv::Vec3b(0, 0, 0)) 77 | { 78 | dst.at(p.y, p.x) = cv::Vec3b(num * 80, 255 - num * 80, 0); 79 | pts.push_back(p); 80 | } 81 | } 82 | } 83 | 84 | ++num; 85 | } 86 | } 87 | } 88 | } 89 | 90 | int main(int argc, char* argv[]) 91 | { 92 | cv::Mat src = cv::imread("1.jpg", 0), dst; 93 | 94 | getconnecteddomain(src, dst); 95 | cv::imwrite("connectiondomain.jpg", dst); 96 | 97 | system("pause"); 98 | return EXIT_SUCCESS; 99 | } 100 | 101 | -------------------------------------------------------------------------------- /gradient.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 计算梯度 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | * @param size 掩膜大小 9 | */ 10 | void gradient(cv::Mat& src, cv::Mat& dst, cv::Size size) 11 | { 12 | cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, size), dst1, dst2; 13 | cv::dilate(src, dst1, element); 14 | cv::erode(src, dst2, element); 15 | dst = dst1 - dst2; 16 | } 17 | 18 | int main(int argc, char* argv[]) 19 | { 20 | cv::Mat src = cv::imread("1.jpg", 0), dst; 21 | 22 | gradient(src, dst, cv::Size(3, 3)); 23 | cv::imwrite("gradient.jpg", dst); 24 | 25 | system("pause"); 26 | return EXIT_SUCCESS; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /gussianfilter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 高斯滤波 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | * @param size 掩膜大小 9 | * @param sigmaX x方向方差 10 | * @param sigmaY y方向方差 11 | */ 12 | void gaussianfilter(cv::Mat& src, cv::Mat& dst, cv::Size size, double sigmaX, double sigmaY) 13 | { 14 | cv::Mat kernel = cv::Mat::zeros(size, CV_64F); 15 | int h = (size.height - 1) / 2, w = (size.width - 1) / 2; 16 | double sum = 0.0; 17 | for (int i = 0; i < size.height; ++i) 18 | { 19 | for (int j = 0; j < size.width; ++j) 20 | { 21 | kernel.at(i, j) = exp(-(pow(i - h, 2) + pow(j - w, 2)) / (2 * sigmaX * sigmaY)); 22 | sum += kernel.at(i, j); 23 | } 24 | } 25 | for (int i = 0; i < size.height; ++i) 26 | { 27 | for (int j = 0; j < size.width; ++j) 28 | { 29 | kernel.at(i, j) /= sum; 30 | } 31 | } 32 | cv::filter2D(src, dst, src.depth(), kernel); 33 | } 34 | 35 | int main(int argc, char* argv[]) 36 | { 37 | cv::Mat src = cv::imread("1.jpg", 0), dst; 38 | 39 | gaussianfilter(src, dst, cv::Size(13, 13), 1, 1); 40 | cv::imwrite("gaussianfilter.jpg", dst); 41 | 42 | system("pause"); 43 | return EXIT_SUCCESS; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /harris.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | void harris(cv::Mat& src, cv::Mat& dst, int block_size, int ksize, float k) 6 | { 7 | dst = src.clone(); 8 | src.convertTo(src, CV_32F); 9 | 10 | double scale = 1.0 / ((ksize - 1) * 2 * block_size * 255); 11 | 12 | cv::Mat img_x, img_y; 13 | cv::Sobel(src, img_x, -1, 1, 0, ksize, scale); 14 | cv::Sobel(src, img_y, -1, 0, 1, ksize, scale); 15 | 16 | cv::Mat img_xx, img_yy, img_xy; 17 | cv::boxFilter(img_x.mul(img_x), img_xx, -1, cv::Size(block_size, block_size)); 18 | cv::boxFilter(img_y.mul(img_y), img_yy, -1, cv::Size(block_size, block_size)); 19 | cv::boxFilter(img_x.mul(img_y), img_xy, -1, cv::Size(block_size, block_size)); 20 | 21 | int radius = int((block_size - 1) / 2); 22 | int N_pre = radius; 23 | int N_post = block_size - radius - 1; 24 | int row_s = N_pre; 25 | int col_s = N_pre; 26 | int row_e = src.rows - N_post; 27 | int col_e = src.cols - N_post; 28 | 29 | cv::Mat cim = cv::Mat::zeros(src.rows, src.cols, CV_32F); 30 | for (int i = row_s; i < row_e; ++i) 31 | { 32 | for (int j = col_s; j < col_e; ++j) 33 | { 34 | float sum_xx = img_xx.at(i, j); 35 | float sum_yy = img_yy.at(i, j); 36 | float sum_xy = img_xy.at(i, j); 37 | 38 | float det = sum_xx * sum_yy - sum_xy * sum_xy; 39 | float trace = sum_xx + sum_yy; 40 | float res = det - k * trace * trace; 41 | cim.at(i, j) = res; 42 | } 43 | } 44 | 45 | double minv, maxv; 46 | cv::Point pt_min, pt_max; 47 | cv::minMaxLoc(cim, &minv, &maxv, &pt_min, &pt_max); 48 | std::cout << maxv << std::endl; 49 | 50 | cv::cvtColor(dst, dst, cv::COLOR_GRAY2BGR); 51 | 52 | int num = 0; 53 | for (int i = 0; i < cim.rows; ++i) 54 | { 55 | for (int j = 0; j < cim.cols; ++j) 56 | { 57 | if (cim.at(i, j) > 0.01* maxv) 58 | { 59 | dst.at(i, j) = cv::Vec3b(0, 0, 255); 60 | num++; 61 | } 62 | } 63 | } 64 | std::cout << num << std::endl; 65 | } 66 | 67 | 68 | int main(int argc, char** argv) 69 | { 70 | cv::Mat src = cv::imread("1.jpg", 0), dst; 71 | cv::Mat srccopy = src.clone(); 72 | 73 | harris(src, dst, 2, 3, 0.04); 74 | cv::imwrite("myharris.jpg", dst); 75 | 76 | system("pause"); 77 | return EXIT_SUCCESS; 78 | } 79 | 80 | -------------------------------------------------------------------------------- /histogram.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 直方图双峰法图像分割 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | */ 9 | void histogram(cv::Mat& src, cv::Mat& dst) 10 | { 11 | double minv, maxv; 12 | cv::Point pt_min, pt_max; 13 | cv::minMaxLoc(src, &minv, &maxv, &pt_min, &pt_max); 14 | double T = (minv + maxv) / 2; 15 | 16 | double thresh = 0; 17 | double histogram[256] = { 0 }; 18 | double totalnum = src.rows*src.cols; 19 | 20 | for (int i = 0; i < src.rows; ++i) 21 | { 22 | const uchar* ptr = src.ptr(i); 23 | for (int j = 0; j < src.cols; ++j) 24 | { 25 | ++histogram[ptr[j]]; 26 | } 27 | } 28 | 29 | while (abs(thresh - T) > 1) 30 | { 31 | T = thresh; 32 | double w0 = 0.0; 33 | double w1 = 0.0; 34 | double u0 = 0.0; 35 | double u1 = 0.0; 36 | 37 | for (int j = 0; j <= T; j++) 38 | { 39 | w1 += histogram[j]; 40 | u1 += j*histogram[j]; 41 | } 42 | 43 | u1 = u1 / w1; 44 | 45 | for (int k = T + 1; k < 256; k++) 46 | { 47 | w0 += histogram[k]; 48 | u0 += k*histogram[k]; 49 | } 50 | 51 | u0 = u0 / w0; 52 | thresh = (u0 + u1) / 2; 53 | } 54 | 55 | dst = src.clone(); 56 | for (int i = 0; i < dst.rows; ++i) 57 | { 58 | uchar* ptr = dst.ptr(i); 59 | for (int j = 0; j < dst.cols; ++j) 60 | { 61 | if (ptr[j] > thresh) 62 | ptr[j] = 255; 63 | else 64 | ptr[j] = 0; 65 | } 66 | } 67 | } 68 | 69 | int main(int argc, char* argv[]) 70 | { 71 | cv::Mat src = cv::imread("1.jpg", 0), dst; 72 | 73 | histogram(src, dst); 74 | cv::imwrite("histogram.jpg", dst); 75 | 76 | system("pause"); 77 | return EXIT_SUCCESS; 78 | } 79 | -------------------------------------------------------------------------------- /hough.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 霍夫变换 6 | * @param edge 输入边缘 7 | * @param lines 检测直线 8 | * @param threshold 阈值 9 | */ 10 | void hough(cv::Mat& edge, std::vector& lines, int threshold) 11 | { 12 | cv::Mat H = cv::Mat::zeros(2 * edge.rows + 2 * edge.cols, 180, CV_16S); 13 | float theta, rho; 14 | 15 | for (int i = 0; i < edge.rows; i++) 16 | { 17 | for (int j = 0; j < edge.cols; j++) 18 | { 19 | if (edge.at(i, j) > 0) 20 | { 21 | for (theta = 0; theta < 180; ++theta) 22 | { 23 | rho = round(i*sin(theta*CV_PI / 180) + j*cos(theta*CV_PI / 180)); 24 | H.at(rho + edge.rows + edge.cols, theta) += 1; 25 | } 26 | } 27 | } 28 | } 29 | 30 | for (int i = 0; i < H.rows; ++i) 31 | { 32 | for (int j = 0; j < H.cols; ++j) 33 | { 34 | if (H.at(i, j) > threshold) 35 | lines.push_back(cv::Vec2f(i - edge.rows - edge.cols, j*CV_PI / 180)); 36 | } 37 | } 38 | } 39 | 40 | int main(int argc, char** argv) 41 | { 42 | cv::Mat src = cv::imread("1.jpg", 0), dst; 43 | cv::Canny(src, dst, 50, 200, 3); 44 | 45 | std::vector lines; 46 | hough(dst, lines, 150); 47 | for (auto line : lines) std::cout << line << std::endl; 48 | for (size_t i = 0; i < lines.size(); i++) 49 | { 50 | float rho = lines[i][0], theta = lines[i][1]; 51 | cv::Point pt1, pt2; 52 | double a = cos(theta), b = sin(theta); 53 | double x0 = a*rho, y0 = b*rho; 54 | pt1.x = round(x0 + 1000 * (-b)); 55 | pt1.y = round(y0 + 1000 * (a)); 56 | pt2.x = round(x0 - 1000 * (-b)); 57 | pt2.y = round(y0 - 1000 * (a)); 58 | cv::line(src, pt1, pt2, cv::Scalar(55, 100, 195), 1, cv::LINE_AA); 59 | } 60 | cv::imwrite("hough.jpg", src); 61 | 62 | system("pause"); 63 | return EXIT_SUCCESS; 64 | } 65 | 66 | -------------------------------------------------------------------------------- /houghlines.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 霍夫变换 6 | * @param edge 输入边缘 7 | * @param lines 检测直线 8 | * @param threshold 阈值 9 | */ 10 | void houghlines(cv::Mat& edge, std::vector& lines, int threshold) 11 | { 12 | cv::Mat H = cv::Mat::zeros(2 * edge.rows + 2 * edge.cols, 180, CV_16S); 13 | float theta, rho; 14 | 15 | for (int i = 0; i < edge.rows; i++) 16 | { 17 | for (int j = 0; j < edge.cols; j++) 18 | { 19 | if (edge.at(i, j) > 0) 20 | { 21 | for (theta = 0; theta < 180; ++theta) 22 | { 23 | rho = round(i*sin(theta*CV_PI / 180) + j*cos(theta*CV_PI / 180)); 24 | H.at(rho + edge.rows + edge.cols, theta) += 1; 25 | } 26 | } 27 | } 28 | } 29 | 30 | for (int i = 0; i < H.rows; ++i) 31 | { 32 | for (int j = 0; j < H.cols; ++j) 33 | { 34 | if (H.at(i, j) > threshold) 35 | lines.push_back(cv::Vec2f(i - edge.rows - edge.cols, j*CV_PI / 180)); 36 | } 37 | } 38 | } 39 | 40 | int main(int argc, char* argv[]) 41 | { 42 | cv::Mat src = cv::imread("1.jpg", 0), dst; 43 | cv::Canny(src, dst, 50, 200, 3); 44 | 45 | std::vector lines; 46 | houghlines(dst, lines, 150); 47 | for (auto line : lines) std::cout << line << std::endl; 48 | for (size_t i = 0; i < lines.size(); i++) 49 | { 50 | float rho = lines[i][0], theta = lines[i][1]; 51 | cv::Point pt1, pt2; 52 | double a = cos(theta), b = sin(theta); 53 | double x0 = a*rho, y0 = b*rho; 54 | pt1.x = round(x0 + 1000 * (-b)); 55 | pt1.y = round(y0 + 1000 * (a)); 56 | pt2.x = round(x0 - 1000 * (-b)); 57 | pt2.y = round(y0 - 1000 * (a)); 58 | cv::line(src, pt1, pt2, cv::Scalar(55, 100, 195), 1, cv::LINE_AA); 59 | } 60 | cv::imwrite("houghlines.jpg", src); 61 | 62 | system("pause"); 63 | return EXIT_SUCCESS; 64 | } 65 | 66 | -------------------------------------------------------------------------------- /laplacian.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 拉普拉斯算子 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | */ 9 | void laplacian(cv::Mat& src, cv::Mat& dst) 10 | { 11 | cv::Mat kernel = (cv::Mat_(3, 3) << 0, 1, 0, 1, -4, 1, 0, 1, 0); 12 | cv::filter2D(src, dst, src.depth(), kernel); 13 | } 14 | 15 | int main(int argc, char* argv[]) 16 | { 17 | cv::Mat src = cv::imread("1.jpg", 0), dst; 18 | 19 | laplacian(src, dst); 20 | cv::imwrite("laplacian.jpg", dst); 21 | 22 | system("pause"); 23 | return EXIT_SUCCESS; 24 | } 25 | -------------------------------------------------------------------------------- /linear.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 双线性插值 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | * @param sx x方向缩放比例 9 | * @param sy y方向缩放比例 10 | */ 11 | void linear(cv::Mat& src, cv::Mat& dst, float sx, float sy) 12 | { 13 | dst = cv::Mat(round(sy*src.rows), round(sx*src.cols), src.type()); 14 | for (int i = 0; i < dst.rows; i++) 15 | { 16 | float index_i = (i + 0.5) / sy - 0.5; 17 | if (index_i < 0) index_i = 0; 18 | if (index_i > src.rows - 1) index_i = src.rows - 1; 19 | int i1 = floor(index_i); 20 | int i2 = ceil(index_i); 21 | float u = index_i - i1; 22 | for (int j = 0; j < dst.cols; j++) 23 | { 24 | float index_j = (j + 0.5) / sx - 0.5; 25 | if (index_j < 0) index_j = 0; 26 | if (index_j > src.cols - 1) index_j = src.cols - 1; 27 | int j1 = floor(index_j); 28 | int j2 = ceil(index_j); 29 | float v = index_j - j1; 30 | dst.at(i, j) = (1 - u)*(1 - v)*src.at(i1, j1) + (1 - u)*v*src.at(i1, j2) + 31 | u*(1 - v)*src.at(i2, j1) + u*v*src.at(i2, j2); 32 | } 33 | } 34 | } 35 | 36 | int main(int argc, char* argv[]) 37 | { 38 | cv::Mat src = cv::imread("1.jpg", 0), dst; 39 | 40 | linear(src, dst, 2, 2); 41 | cv::imwrite("linear.jpg", dst); 42 | 43 | system("pause"); 44 | return EXIT_SUCCESS; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /maxentropy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 最大熵值法图像分割 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | */ 9 | void maxentropy(cv::Mat& src, cv::Mat& dst) 10 | { 11 | int thresh = 0; 12 | int histogram[256] = { 0 }; 13 | for (int i = 0; i < src.rows; ++i) 14 | { 15 | const uchar* ptr = src.ptr(i); 16 | for (int j = 0; j < src.cols; ++j) 17 | { 18 | if (ptr[j] == 0) continue; 19 | histogram[ptr[j]]++; 20 | } 21 | } 22 | 23 | float p = 0.0; 24 | float max_entropy = 0.0; 25 | int totalnum = src.rows*src.cols; 26 | for (int i = 0; i < 256; ++i) 27 | { 28 | float front_entropy = 0.0; 29 | float back_entropy = 0.0; 30 | 31 | int frontnum = 0; 32 | for (int j = 0; j < i; ++j) 33 | { 34 | frontnum += histogram[j]; 35 | } 36 | for (int j = 0; j < i; ++j) 37 | { 38 | if (histogram[j] != 0) 39 | { 40 | p = (float)histogram[j] / frontnum; 41 | front_entropy += p*log(1 / p); 42 | } 43 | } 44 | 45 | for (int k = i; k < 256; ++k) 46 | { 47 | if (histogram[k] != 0) 48 | { 49 | p = (float)histogram[k] / (totalnum - frontnum); 50 | back_entropy += p*log(1 / p); 51 | } 52 | } 53 | 54 | if (front_entropy + back_entropy > max_entropy) 55 | { 56 | max_entropy = front_entropy + back_entropy; 57 | thresh = i ; 58 | } 59 | } 60 | 61 | dst = src.clone(); 62 | for (int i = 0; i < dst.rows; ++i) 63 | { 64 | uchar* ptr = dst.ptr(i); 65 | for (int j = 0; j < dst.cols; ++j) 66 | { 67 | if (ptr[j] > thresh) 68 | ptr[j] = 255; 69 | else 70 | ptr[j] = 0; 71 | } 72 | } 73 | } 74 | 75 | int main(int argc, char* argv[]) 76 | { 77 | cv::Mat src = cv::imread("1.jpg", 0), dst; 78 | 79 | maxentropy(src, dst); 80 | cv::imwrite("maxentropy.jpg", dst); 81 | 82 | system("pause"); 83 | return EXIT_SUCCESS; 84 | } 85 | -------------------------------------------------------------------------------- /medianfilter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 计算掩膜的中值 6 | * @param kernel 掩膜 7 | * @return 掩膜的中值 8 | */ 9 | int getmedian(cv::Mat& kernel) 10 | { 11 | std::vector v; 12 | for (int i = 0; i < kernel.rows; ++i) 13 | { 14 | for (int j = 0; j < kernel.cols; ++j) 15 | { 16 | v.push_back(kernel.at(i, j)); 17 | } 18 | } 19 | sort(v.begin(), v.end()); 20 | return v[v.size() / 2]; 21 | } 22 | 23 | /** 24 | * @description: 中值滤波 25 | * @param src 输入图像 26 | * @param dst 输出图像 27 | * @param ksize 掩膜大小 28 | */ 29 | void medianfilter(cv::Mat& src, cv::Mat& dst, int ksize) 30 | { 31 | dst = cv::Mat::zeros(src.size(), src.type()); 32 | cv::Mat mid; 33 | int k = (ksize - 1) / 2; 34 | cv::copyMakeBorder(src, mid, k, k, k, k, cv::BORDER_REPLICATE); 35 | for (int i = k; i < src.rows + k; ++i) 36 | { 37 | for (int j = k; j < src.cols + k; ++j) 38 | { 39 | cv::Mat kernel = mid(cv::Rect(j - k, i - k, ksize, ksize)); 40 | dst.at(i - k, j - k) = getmedian(kernel); 41 | } 42 | } 43 | } 44 | 45 | int main(int argc, char* argv[]) 46 | { 47 | cv::Mat src = cv::imread("1.jpg", 0), dst; 48 | 49 | medianfilter(src, dst, 3); 50 | cv::imwrite("medianfilter.jpg", dst); 51 | 52 | system("pause"); 53 | return EXIT_SUCCESS; 54 | } 55 | -------------------------------------------------------------------------------- /modelmatch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 模板匹配 6 | * @param src 输入图像 7 | * @param temp 模板图像 8 | * @param dst 输出图像 9 | */ 10 | void matchtemplate(cv::Mat& src, cv::Mat& temp, cv::Mat& dst) 11 | { 12 | for (int i = 0; i < dst.cols; ++i) 13 | { 14 | for (int j = 0; j < dst.rows; ++j) 15 | { 16 | int R = 0; 17 | for (int m = 0; m < temp.cols; ++m) 18 | { 19 | for (int n = 0; n < temp.rows; ++n) 20 | { 21 | R += pow(src.at(j + n, i + m) - temp.at(n, m), 2); 22 | } 23 | } 24 | dst.at(j, i) = R; 25 | } 26 | } 27 | } 28 | 29 | int main(int argc, char* argv[]) 30 | { 31 | cv::Mat src = cv::imread("1.jpg", 0), temp = cv::imread("1part.jpg", 0), dst; 32 | dst.create(cv::Size(src.cols - temp.cols + 1, src.rows - temp.rows + 1), CV_32SC1); 33 | 34 | matchtemplate(src, temp, dst); 35 | double minValue, maxValue; 36 | cv::Point minLocation, maxLocation; 37 | cv::minMaxLoc(dst, &minValue, &maxValue, &minLocation, &maxLocation); 38 | std::cout << minLocation << std::endl; 39 | 40 | system("pause"); 41 | return EXIT_SUCCESS; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /nearest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 最近邻插值 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | * @param sx x方向缩放比例 9 | * @param sy y方向缩放比例 10 | */ 11 | void nearest(cv::Mat& src, cv::Mat& dst, float sx, float sy) 12 | { 13 | dst = cv::Mat(round(src.rows * sy), round(src.cols * sx), src.type()); 14 | for (int i = 0; i < dst.rows; i++) 15 | { 16 | float index_i = (i + 0.5) / sy - 0.5; 17 | if (index_i < 0) index_i = 0; 18 | if (index_i > src.rows - 1) index_i = src.rows - 1; 19 | int i_index = round(index_i); 20 | for (int j = 0; j < dst.cols; j++) 21 | { 22 | float index_j = (j + 0.5) / sx - 0.5; 23 | if (index_j < 0) index_j = 0; 24 | if (index_j > src.cols - 1) index_j = src.cols - 1; 25 | int j_index = round(index_j); 26 | dst.at(i, j) = src.at(i_index, j_index); 27 | } 28 | } 29 | } 30 | 31 | int main(int argc, char* argv[]) 32 | { 33 | cv::Mat src = cv::imread("1.jpg", 0), dst; 34 | 35 | nearest(src, dst, 2, 2); 36 | cv::imwrite("nearest.jpg", dst); 37 | 38 | system("pause"); 39 | return EXIT_SUCCESS; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /open.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 开运算 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | * @param size 掩膜大小 9 | */ 10 | void open(cv::Mat& src, cv::Mat& dst, cv::Size size) 11 | { 12 | cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, size); 13 | cv::erode(src, dst, element); 14 | cv::dilate(dst, dst, element); 15 | } 16 | 17 | int main(int argc, char* argv[]) 18 | { 19 | cv::Mat src = cv::imread("1.jpg", 0), dst; 20 | 21 | open(src, dst, cv::Size(3, 3)); 22 | cv::imwrite("open.jpg", dst); 23 | 24 | system("pause"); 25 | return EXIT_SUCCESS; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /orb.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define _USE_MATH_DEFINES 4 | #include 5 | #include 6 | 7 | 8 | int kBytes = 32; 9 | int nfeatures = 500; 10 | float scaleFactor = 1.2; 11 | int nlevels = 8; 12 | int edgeThreshold = 31; 13 | int firstLevel = 0; 14 | int wta_k = 2; 15 | int scoreType = 0; 16 | int patchSize = 31; 17 | int fastThreshold = 20; 18 | float harris_k = 0.04; 19 | 20 | 21 | float getScale(int level, int firstLevel, float scaleFactor) 22 | { 23 | return pow(scaleFactor, level - firstLevel); 24 | } 25 | 26 | 27 | template 28 | std::vector sort_indices(const std::vector& v) 29 | { 30 | std::vector idx(v.size()); 31 | std::iota(idx.begin(), idx.end(), 0); 32 | std::sort(idx.begin(), idx.end(), [&v](size_t i1, size_t i2) { return v[i1] < v[i2]; }); 33 | return idx; 34 | } 35 | 36 | 37 | std::vector retainBest(std::vector keypoints, int n_points) 38 | { 39 | if (n_points >= 0 && keypoints.size() > n_points) 40 | { 41 | std::vector res; 42 | for (auto kp : keypoints) 43 | res.push_back(kp.response); 44 | std::vector index = sort_indices(res); 45 | std::reverse(index.begin(), index.end()); 46 | std::vector new_keypoints; 47 | for (size_t i = 0; i < n_points; i++) 48 | new_keypoints.push_back(keypoints[index[i]]); 49 | return new_keypoints; 50 | } 51 | return keypoints; 52 | } 53 | 54 | 55 | void HarrisResponses(cv::Mat img, std::vector> layerinfo, std::vector& pts, int blockSize) 56 | { 57 | int radius = int(blockSize / 2); 58 | float scale = 1.0 / ((1 << 2) * blockSize * 255.0); 59 | float scale_sq_sq = pow(scale, 4); 60 | 61 | for (size_t i = 0; i < pts.size(); i++) 62 | { 63 | int x0 = int(round(pts[i].pt.x)); 64 | int y0 = int(round(pts[i].pt.y)); 65 | int z = int(pts[i].octave); 66 | 67 | int center_c = layerinfo[z][0] + x0; 68 | int center_r = layerinfo[z][1] + y0; 69 | long long a = 0, b = 0, c = 0; 70 | for (int index_r = - radius; index_r < blockSize - radius; index_r++) 71 | { 72 | for (int index_c = - radius; index_c < blockSize - radius; index_c++) 73 | { 74 | int rr = center_r + index_r; 75 | int cc = center_c + index_c; 76 | 77 | int Ix = (img.at(rr, cc + 1) - img.at(rr, cc - 1)) * 2 + 78 | (img.at(rr - 1, cc + 1) - img.at(rr - 1, cc - 1)) + 79 | (img.at(rr + 1, cc + 1) - img.at(rr + 1, cc - 1)); 80 | 81 | int Iy = (img.at(rr + 1, cc ) - img.at(rr - 1, cc )) * 2 + 82 | (img.at(rr + 1, cc - 1) - img.at(rr - 1, cc - 1)) + 83 | (img.at(rr + 1, cc + 1) - img.at(rr - 1, cc + 1)); 84 | 85 | a += Ix * Ix; 86 | b += Iy * Iy; 87 | c += Ix * Iy; 88 | } 89 | } 90 | pts[i].response = (a * b - c * c - harris_k * (a + b) * (a + b)) * scale_sq_sq; 91 | } 92 | } 93 | 94 | 95 | void ICAngles(cv::Mat img, std::vector> layerinfo, std::vector& pts, std::vector u_max, int half_k) 96 | { 97 | for (size_t i = 0; i < pts.size(); i++) 98 | { 99 | std::vector layer = layerinfo[pts[i].octave]; 100 | int c = round(pts[i].pt.x) + layer[0], r = round(pts[i].pt.y) + layer[1]; 101 | int m_01 = 0, m_10 = 0; 102 | 103 | for (int u = -half_k; u < half_k + 1; u++) 104 | m_10 += u * img.at(r, c + u); 105 | 106 | for (int v = 1; v < half_k + 1; v++) 107 | { 108 | int v_sum = 0, d = u_max[v]; 109 | for (int u = - d; u < d + 1; u++) 110 | { 111 | int val_plus= img.at(r + v, c + u); 112 | int val_minus = img.at(r - v, c + u); 113 | v_sum += (val_plus - val_minus); 114 | m_10 += u * (val_plus + val_minus); 115 | } 116 | m_01 += v * v_sum; 117 | } 118 | 119 | pts[i].angle = cv::fastAtan2(float(m_01), float(m_10)); 120 | } 121 | } 122 | 123 | 124 | std::vector computeKeyPoints(cv::Mat imagePyramid, std::vector> layerInfo, std::vector layerScale) 125 | { 126 | 127 | int nlevels = layerInfo.size(); 128 | std::vector nfeaturesPerLevel; 129 | float factor = float(1.0 / scaleFactor); 130 | float ndesiredFeaturesPerScale = nfeatures * (1 - factor) / (1 - pow(factor, nlevels)); 131 | int sumFeatures = 0; 132 | for (size_t level = 0; level < nlevels - 1; level++) 133 | { 134 | nfeaturesPerLevel.push_back(int(round(ndesiredFeaturesPerScale))); 135 | sumFeatures += nfeaturesPerLevel[level]; 136 | ndesiredFeaturesPerScale *= factor; 137 | } 138 | nfeaturesPerLevel.push_back(std::max(nfeatures - sumFeatures, 0)); 139 | int halfPatchSize = int(patchSize / 2); 140 | std::vector allKeypoints; 141 | std::vector counters; 142 | 143 | for (size_t level = 0; level < nlevels; level++) 144 | { 145 | int featuresNum = int(nfeaturesPerLevel[level]); 146 | std::vector r = layerInfo[level]; 147 | cv::Mat img = imagePyramid(cv::Rect(r[0], r[1], r[2], r[3])); 148 | cv::Ptr fast = cv::FastFeatureDetector::create(fastThreshold); 149 | std::vector keypoints; 150 | fast->detect(img, keypoints); 151 | cv::KeyPointsFilter::runByImageBorder(keypoints, img.size(), edgeThreshold); 152 | keypoints = retainBest(keypoints, 2 * featuresNum); 153 | int nkeypoints = keypoints.size(); 154 | counters.push_back(nkeypoints); 155 | float sf = layerScale[level]; 156 | for (size_t i = 0; i < nkeypoints; i++) 157 | { 158 | keypoints[i].octave = level; 159 | keypoints[i].size = patchSize * sf; 160 | } 161 | for (auto kp : keypoints) 162 | allKeypoints.push_back(kp); 163 | } 164 | int nkeypoints = allKeypoints.size(); 165 | if (nkeypoints == 0) 166 | return {}; 167 | 168 | HarrisResponses(imagePyramid, layerInfo, allKeypoints, 7); 169 | std::vector newAllKeypoints; 170 | int offset = 0; 171 | 172 | for (size_t level = 0; level < nlevels; level++) 173 | { 174 | std::vector keypoints; 175 | int featuresNum = int(nfeaturesPerLevel[level]); 176 | int nkeypoints = int(counters[level]); 177 | for (size_t i = offset; i < offset + nkeypoints; i++) 178 | keypoints.push_back(allKeypoints[i]); 179 | offset += nkeypoints; 180 | std::vector keypoints2 = retainBest(keypoints, featuresNum); 181 | for(auto kp: keypoints2) 182 | newAllKeypoints.push_back(kp); 183 | } 184 | 185 | allKeypoints = newAllKeypoints; 186 | nkeypoints = allKeypoints.size(); 187 | 188 | std::vector umax(halfPatchSize + 2, 0); 189 | int vmax = int(floor((halfPatchSize * sqrt(2.) / 2 + 1))); 190 | for (int v = 0; v < vmax + 1; ++v) 191 | umax[v] = round(sqrt(double(pow(halfPatchSize, 2) - pow(v, 2)))); 192 | int vmin = ceil(halfPatchSize * sqrt(2.0) / 2); 193 | 194 | int v = halfPatchSize, v0 = 0; 195 | while (v >= vmin) 196 | { 197 | while (umax[v0] == umax[v0 + 1]) 198 | v0 = v0 + 1; 199 | umax[v] = v0; 200 | v0 = v0 + 1; 201 | v = v - 1; 202 | } 203 | 204 | ICAngles(imagePyramid, layerInfo, allKeypoints, umax, halfPatchSize); 205 | 206 | for (size_t i = 0; i < nkeypoints; i++) 207 | { 208 | float scale = layerScale[allKeypoints[i].octave]; 209 | allKeypoints[i].pt = cv::Point(allKeypoints[i].pt.x * scale, allKeypoints[i].pt.y * scale); 210 | } 211 | return allKeypoints; 212 | } 213 | 214 | 215 | float GET_VALUE(int idx, std::vector pattern, float a, float b, cv::Mat imagePyramid, int cx, int cy) 216 | { 217 | float x = pattern[idx].x * a - pattern[idx].y * b; 218 | float y = pattern[idx].x * b + pattern[idx].y * a; 219 | int ix = int(round(x)); 220 | int iy = int(round(y)); 221 | return imagePyramid.at(cy + iy, cx + ix); 222 | } 223 | 224 | 225 | std::vector> computeOrbDescriptors(cv::Mat imagePyramid, std::vector> layerInfo, 226 | std::vector layerScale, std::vector keypoints, std::vector _pattern, int dsize) 227 | { 228 | std::vector> descriptors; 229 | for (size_t i = 0; i < keypoints.size(); i++) 230 | { 231 | cv::KeyPoint kpt = keypoints[i]; 232 | std::vector layer = layerInfo[int(kpt.octave)]; 233 | float scale = 1.0 / layerScale[int(kpt.octave)]; 234 | float angle = kpt.angle / 180.0 * M_PI; 235 | float a = cos(angle), b = sin(angle); 236 | 237 | int cx = round(kpt.pt.x * scale) + layer[0], cy = round(kpt.pt.y * scale) + layer[1]; 238 | int pattern_idx = 0; 239 | 240 | std::vector pattern; 241 | pattern.assign(_pattern.begin()+ pattern_idx, _pattern.end()); 242 | std::vector des; 243 | for (size_t j = 0; j < dsize; j++) 244 | { 245 | int byte_v = 0; 246 | for (size_t nn = 0; nn < 8; nn++) 247 | { 248 | float t0 = GET_VALUE(2 * nn, pattern, a, b, imagePyramid, cx, cy); 249 | float t1 = GET_VALUE(2 * nn + 1, pattern, a, b, imagePyramid, cx, cy); 250 | int bit_v = int(t0 < t1); 251 | byte_v += (bit_v << nn); 252 | } 253 | des.push_back(byte_v); 254 | pattern_idx += 16; 255 | pattern.assign(_pattern.begin() + pattern_idx, _pattern.end()); 256 | } 257 | descriptors.push_back(des); 258 | } 259 | return descriptors; 260 | } 261 | 262 | 263 | std::tuple, std::vector>> orb_detectAndCompute(cv::Mat img_src) 264 | { 265 | int HARRIS_BLOCK_SIZE = 9; 266 | int halfPatchSize = int(patchSize / 2); 267 | int descPatchSize = int(ceil(halfPatchSize * sqrt(2.0))); 268 | std::vector vec = { edgeThreshold, descPatchSize, HARRIS_BLOCK_SIZE / 2 }; 269 | int border = int(*std::max_element(vec.begin(),vec.end()) + 1); 270 | cv::Mat image = img_src.clone(); 271 | 272 | std::vector layerScale; 273 | std::vector> layerInfo; 274 | int level_dy = (int)(image.cols + border * 2); 275 | cv::Point level_ofs(0, 0); 276 | int tmp = round(image.cols / getScale(0, firstLevel, scaleFactor)) + border * 2 + 15; 277 | cv::Size bufSize(tmp / 16 * 16, 0); 278 | 279 | for (size_t level = 0; level < nlevels; level++) 280 | { 281 | float scale = getScale(level, firstLevel, scaleFactor); 282 | layerScale.push_back(scale); 283 | cv::Size sz(int(round(image.cols / scale)), int(round(image.rows / scale))); 284 | cv::Size wholeSize(sz.width + border * 2, sz.height + border * 2); 285 | if (level_ofs.x + wholeSize.width > bufSize.width) 286 | { 287 | level_ofs = cv::Point(0, level_ofs.y + level_dy); 288 | level_dy = wholeSize.height; 289 | } 290 | std::vector linfo = { level_ofs.x + border, level_ofs.y + border, sz.width, sz.height }; 291 | layerInfo.push_back(linfo); 292 | level_ofs.x += wholeSize.width; 293 | } 294 | bufSize.height = level_ofs.y + level_dy; 295 | 296 | cv::Mat imagePyramid(bufSize, CV_8UC1); 297 | 298 | cv::Mat prevImg = image; 299 | for (size_t level = 0; level < nlevels; level++) 300 | { 301 | std::vector linfo = layerInfo[level]; 302 | cv::Size sz(linfo[2],linfo[3]); 303 | cv::Size wholeSize(sz.width + border * 2, sz.height + border * 2); 304 | std::vector wholeLinfo = { linfo[0] - border, linfo[1] - border, wholeSize.width, wholeSize.height }; 305 | cv::Mat extImg, currImg; 306 | if (level == firstLevel) 307 | { 308 | cv::copyMakeBorder(image, extImg, border, border, border, border, cv::BORDER_REFLECT_101); 309 | } 310 | else 311 | { 312 | cv::resize(prevImg, currImg, sz, 0, 0, cv::INTER_LINEAR_EXACT); 313 | cv::copyMakeBorder(currImg, extImg, border, border, border, border, cv::BORDER_REFLECT_101 + cv::BORDER_ISOLATED); 314 | } 315 | cv::Mat roi = imagePyramid(cv::Rect(wholeLinfo[0], wholeLinfo[1], wholeLinfo[2], wholeLinfo[3])); 316 | extImg.copyTo(roi); 317 | if (level > firstLevel) 318 | prevImg = currImg.clone(); 319 | } 320 | 321 | imagePyramid = cv::imread("imagePyramid.png", 0); 322 | 323 | std::vector keypoints = computeKeyPoints(imagePyramid, layerInfo, layerScale); 324 | 325 | int dsize = kBytes; 326 | int nkeypoints = keypoints.size(); 327 | int npoints = 512; 328 | 329 | #include "bit_pattern_31.i" 330 | 331 | std::vector pattern; 332 | for (size_t i = 0; i < npoints; i++) 333 | pattern.push_back(cv::Point(bit_pattern_31_[2 * i], bit_pattern_31_[2 * i + 1])); 334 | 335 | imagePyramid.convertTo(imagePyramid, CV_32F); 336 | for (size_t level = 0; level < nlevels; level++) 337 | { 338 | int x = layerInfo[level][0], y = layerInfo[level][1], w = layerInfo[level][2], h = layerInfo[level][3]; 339 | cv::Mat workingMat = imagePyramid(cv::Rect(x, y, w, h)); 340 | workingMat.convertTo(workingMat, CV_32F); 341 | cv::GaussianBlur(workingMat, workingMat, cv::Size(7, 7), 2, 2, cv::BORDER_REFLECT_101); 342 | } 343 | //cv::imwrite("imagePyramid.png", imagePyramid); 344 | 345 | std::vector> descriptors = computeOrbDescriptors(imagePyramid, layerInfo, layerScale, keypoints, pattern, dsize); 346 | 347 | return { keypoints, descriptors }; 348 | } 349 | 350 | 351 | int main() 352 | { 353 | cv::Mat img = cv::imread("1.png", 0); 354 | 355 | auto [kp, des] = orb_detectAndCompute(img); 356 | 357 | return 0; 358 | } -------------------------------------------------------------------------------- /prewitt.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: prewitt算子 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | */ 9 | void prewitt(cv::Mat& src, cv::Mat& dst) 10 | { 11 | cv::Mat getPrewitt_horizontal = (cv::Mat_(3, 3) << -1, -1, -1, 0, 0, 0, 1, 1, 1); 12 | cv::Mat getPrewitt_vertical = (cv::Mat_(3, 3) << -1, 0, 1, -1, 0, 1, -1, 0, 1); 13 | cv::Mat getPrewitt_diagonal1 = (cv::Mat_(3, 3) << -1, -1, 0, -1, 0, 1, 0, 1, 1); 14 | cv::Mat getPrewitt_diagonal2 = (cv::Mat_(3, 3) << 0, 1, 1, -1, 0, 1, -1, -1, 0); 15 | 16 | cv::flip(getPrewitt_horizontal, getPrewitt_horizontal, -1); 17 | cv::flip(getPrewitt_vertical, getPrewitt_vertical, -1); 18 | cv::flip(getPrewitt_diagonal1, getPrewitt_diagonal1, -1); 19 | cv::flip(getPrewitt_diagonal2, getPrewitt_diagonal2, -1); 20 | 21 | cv::Mat dst1, dst2, dst3, dst4; 22 | cv::filter2D(src, dst1, src.depth(), getPrewitt_horizontal); 23 | cv::filter2D(src, dst2, src.depth(), getPrewitt_vertical); 24 | cv::filter2D(src, dst3, src.depth(), getPrewitt_diagonal1); 25 | cv::filter2D(src, dst4, src.depth(), getPrewitt_diagonal2); 26 | 27 | cv::convertScaleAbs(dst1, dst1); 28 | cv::convertScaleAbs(dst2, dst2); 29 | cv::convertScaleAbs(dst3, dst3); 30 | cv::convertScaleAbs(dst4, dst4); 31 | dst = dst1 + dst2; 32 | } 33 | 34 | int main(int argc, char* argv[]) 35 | { 36 | cv::Mat src = cv::imread("1.jpg", 0), dst; 37 | 38 | prewitt(src, dst); 39 | cv::imwrite("prewitt.jpg", dst); 40 | 41 | system("pause"); 42 | return EXIT_SUCCESS; 43 | } 44 | -------------------------------------------------------------------------------- /regiongrow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 区域生长算法 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | * @param pt 种子点 9 | * @param threshold 阈值 10 | */ 11 | void regiongrow(cv::Mat& src, cv::Mat& dst, cv::Point pt, int threshold) 12 | { 13 | cv::Point ptGrowing; 14 | int srcval = src.at(pt.y, pt.x); 15 | dst = cv::Mat::zeros(src.size(), CV_8UC1); 16 | int DIR[8][2] = { { -1, -1 }, { 0, -1 }, { 1, -1 }, { 1, 0 }, { 1, 1 }, { 0, 1 }, { -1, 1 }, { -1, 0 } }; 17 | std::vector ptGrow; 18 | ptGrow.push_back(pt); 19 | dst.at(pt.y, pt.x) = 255; 20 | 21 | while (!ptGrow.empty()) 22 | { 23 | pt = ptGrow.back(); 24 | ptGrow.pop_back(); 25 | 26 | for (int i = 0; i < 8; ++i) 27 | { 28 | ptGrowing.x = pt.x + DIR[i][0]; 29 | ptGrowing.y = pt.y + DIR[i][1]; 30 | if (ptGrowing.x < 0 || ptGrowing.y < 0 || ptGrowing.x >=src.cols || ptGrowing.y >= src.rows) 31 | continue; 32 | 33 | if (dst.at(ptGrowing.y, ptGrowing.x) == 0) 34 | { 35 | int curval = src.at(ptGrowing.y, ptGrowing.x); 36 | if (abs(srcval - curval) < threshold) 37 | { 38 | dst.at(ptGrowing.y, ptGrowing.x) = 255; 39 | ptGrow.push_back(ptGrowing); 40 | } 41 | } 42 | 43 | } 44 | } 45 | } 46 | 47 | int main(int argc, char* argv[]) 48 | { 49 | cv::Mat src = cv::imread("1.jpg", 0), dst; 50 | 51 | regiongrow(src, dst, cv::Point(100, 100), 50); 52 | cv::imwrite("regiongrow.jpg", dst); 53 | 54 | system("pause"); 55 | return EXIT_SUCCESS; 56 | } 57 | -------------------------------------------------------------------------------- /roberts.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: roberts算子 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | */ 9 | void roberts(cv::Mat& src, cv::Mat& dst) 10 | { 11 | cv::Mat oper1 = (cv::Mat_(2, 2) << 0, 1, -1, 0); 12 | cv::Mat oper2 = (cv::Mat_(2, 2) << 1, 0, -1, 0); 13 | cv::flip(oper1, oper1, -1); 14 | cv::flip(oper2, oper2, -1); 15 | cv::Mat dst1, dst2; 16 | 17 | cv::filter2D(src, dst1, src.depth(), oper1); 18 | cv::filter2D(src, dst2, src.depth(), oper2); 19 | 20 | cv::convertScaleAbs(dst1, dst1); 21 | cv::convertScaleAbs(dst2, dst2); 22 | dst = dst1 + dst2; 23 | } 24 | 25 | int main(int argc, char* argv[]) 26 | { 27 | cv::Mat src = cv::imread("1.jpg", 0), dst; 28 | 29 | roberts(src, dst); 30 | cv::imwrite("roberts.jpg", dst); 31 | 32 | system("pause"); 33 | return EXIT_SUCCESS; 34 | } 35 | -------------------------------------------------------------------------------- /shi-tomas.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | void shi_tomas(cv::Mat& src, cv::Mat& dst, int maxCorners, float qualityLevel, int minDistance) 6 | { 7 | int block_size = 3; 8 | int ksize = 3; 9 | float k = 0.04; 10 | 11 | dst = src.clone(); 12 | src.convertTo(src, CV_32F); 13 | 14 | double scale = 1.0 / ((ksize - 1) * 2 * block_size * 255); 15 | 16 | cv::Mat img_x, img_y; 17 | cv::Sobel(src, img_x, -1, 1, 0, ksize, scale); 18 | cv::Sobel(src, img_y, -1, 0, 1, ksize, scale); 19 | 20 | cv::Mat img_xx, img_yy, img_xy; 21 | cv::boxFilter(img_x.mul(img_x), img_xx, -1, cv::Size(block_size, block_size)); 22 | cv::boxFilter(img_y.mul(img_y), img_yy, -1, cv::Size(block_size, block_size)); 23 | cv::boxFilter(img_x.mul(img_y), img_xy, -1, cv::Size(block_size, block_size)); 24 | 25 | int radius = int((block_size - 1) / 2); 26 | int N_pre = radius; 27 | int N_post = block_size - radius - 1; 28 | int row_s = N_pre; 29 | int col_s = N_pre; 30 | int row_e = src.rows - N_post; 31 | int col_e = src.cols - N_post; 32 | 33 | cv::Mat cim = cv::Mat::zeros(src.rows, src.cols, CV_32F); 34 | for (int i = row_s; i < row_e; ++i) 35 | { 36 | for (int j = col_s; j < col_e; ++j) 37 | { 38 | float sum_xx = img_xx.at(i, j); 39 | float sum_yy = img_yy.at(i, j); 40 | float sum_xy = img_xy.at(i, j); 41 | cim.at(i, j) = 0.5 * (sum_xx + sum_yy) - 0.5 * sqrt(pow(sum_xx - sum_yy, 2) + 4 * pow(sum_xy, 2)); 42 | } 43 | } 44 | 45 | double minv, maxv; 46 | cv::Point pt_min, pt_max; 47 | cv::minMaxLoc(cim, &minv, &maxv, &pt_min, &pt_max); 48 | 49 | for (int i = 0; i < cim.rows; ++i) 50 | { 51 | for (int j = 0; j < cim.cols; ++j) 52 | { 53 | if (cim.at(i, j) < maxv * qualityLevel) 54 | { 55 | cim.at(i, j) = 0; 56 | } 57 | } 58 | } 59 | 60 | cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)), dilated; 61 | cv::dilate(cim, dilated, element); 62 | 63 | for (int i = 0; i < cim.rows; ++i) 64 | { 65 | for (int j = 0; j < cim.cols; ++j) 66 | { 67 | if (cim.at(i, j) != dilated.at(i, j)) 68 | { 69 | cim.at(i, j) = 0; 70 | } 71 | } 72 | } 73 | 74 | int num = 0; 75 | cv::cvtColor(dst, dst, cv::COLOR_GRAY2BGR); 76 | while (num < maxCorners) 77 | { 78 | cv::minMaxLoc(cim, &minv, &maxv, &pt_min, &pt_max); 79 | if (maxv == 0) 80 | break; 81 | 82 | dst.at(pt_max.y, pt_max.x) = cv::Vec3b(0, 0, 255); 83 | num++; 84 | 85 | for (int y = pt_max.y - minDistance; y <= pt_max.y + minDistance; ++y) 86 | { 87 | if (y < 0 || y >= cim.rows) 88 | continue; 89 | for (int x = pt_max.x - minDistance; x <= pt_max.x + minDistance; ++x) 90 | { 91 | if (x < 0 || x >= cim.cols) 92 | continue; 93 | if (sqrt(pow(y - pt_max.y, 2) + pow(x - pt_max.x, 2)) <= minDistance) 94 | { 95 | cim.at(y, x) = 0; 96 | } 97 | } 98 | } 99 | } 100 | 101 | std::cout << num << std::endl; 102 | } 103 | 104 | 105 | int main(int argc, char** argv) 106 | { 107 | cv::Mat src = cv::imread("1.jpg", 0), dst; 108 | 109 | shi_tomas(src, dst, 1000, 0.01, 7); 110 | cv::imwrite("my-shi-tomas.jpg", dst); 111 | 112 | system("pause"); 113 | return EXIT_SUCCESS; 114 | } 115 | 116 | -------------------------------------------------------------------------------- /sift.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define _USE_MATH_DEFINES 5 | #include 6 | 7 | 8 | class Sift 9 | { 10 | public: 11 | Sift(cv::Mat img) 12 | { 13 | m_img = img.clone(); 14 | m_r = m_img.rows, m_c = m_img.cols; 15 | m_gradient = cv::Mat::zeros(m_r, m_c, CV_32F); 16 | m_angle = cv::Mat::zeros(m_r, m_c, CV_32F); 17 | }; 18 | 19 | std::tuple get_result() 20 | { 21 | cv::goodFeaturesToTrack(m_img, m_corners, 233, 0.01, 10); 22 | //std::cout << corners << std::endl; 23 | 24 | cv::GaussianBlur(m_img, m_img, cv::Size(5, 5), 1, 1); 25 | m_img.convertTo(m_img, CV_32F); 26 | 27 | grad(m_img); 28 | 29 | m_bins = (m_r + m_c) / 80; 30 | m_length = m_corners.rows; 31 | m_feature = cv::Mat::zeros(m_length, 128, CV_32F); 32 | 33 | vote(); 34 | 35 | for (size_t i = 0; i < m_length; i++) 36 | { 37 | cv::Point2f p(m_corners.at(i, 1), m_corners.at(i, 0)); 38 | std::vector val = get_feature(p, m_direct[i]); 39 | float m = 0; 40 | for (float k : val) 41 | m += k * k; 42 | m = sqrt(m); 43 | std::vector l; 44 | for (float k : val) 45 | l.push_back(k / m); 46 | cv::Mat temp_row = cv::Mat(l).reshape(1, 1); 47 | //std::cout << temp_row << std::endl; 48 | temp_row.copyTo(m_feature.row(i)); 49 | } 50 | //std::cout << m_feature << std::endl; 51 | return { m_feature, m_corners, m_length }; 52 | } 53 | 54 | void grad(cv::Mat img) 55 | { 56 | int x = m_r, y = m_c; 57 | 58 | cv::Mat kernel_x = (cv::Mat_(3, 3) << -1, -1, -1, 0, 0, 0, 1, 1, 1) / 6; 59 | cv::Mat kernel_y = (cv::Mat_(3, 3) << -1, 0, 1, -1, 0, 1, -1, 0, 1) / 6; 60 | 61 | cv::Mat gx, gy; 62 | cv::filter2D(img, gx, -1, kernel_x); 63 | cv::filter2D(img, gy, -1, kernel_y); 64 | //std::cout << gx.at(1, 0) << std::endl; 65 | //std::cout << gy.at(1, 0) << std::endl; 66 | 67 | for (size_t i = 0; i < x; i++) 68 | { 69 | for (size_t j = 0; j < y; j++) 70 | { 71 | m_gradient.at(i, j) = sqrt(pow(gx.at(i, j), 2) + pow(gy.at(i, j), 2)); 72 | m_angle.at(i, j) = atan2(gy.at(i, j), gx.at(i, j)); 73 | } 74 | } 75 | //std::cout << gradient.at(0, 1) << std::endl; 76 | //std::cout << angle.at(0, 1) << std::endl; 77 | } 78 | 79 | void vote() 80 | { 81 | for (size_t n = 0; n < m_length; n++) 82 | { 83 | int y = m_corners.at(n, 0), x = m_corners.at(n, 1); 84 | 85 | std::vector voting(37); 86 | 87 | for (size_t i = std::max(x - m_bins, 0); i < std::min(x + m_bins + 1, m_r); i++) 88 | { 89 | for (size_t j = std::max(y - m_bins, 0); j < std::min(y + m_bins + 1, m_c); j++) 90 | { 91 | int k = int((m_angle.at(i, j) + M_PI) / (M_PI / 18) + 1); 92 | if (k >= 37) 93 | k = 36; 94 | voting[k] += m_gradient.at(i, j); 95 | } 96 | } 97 | 98 | int p = 1; 99 | for (size_t i = 2; i < 37; i++) 100 | { 101 | if (voting[i] > voting[p]) 102 | p = i; 103 | } 104 | m_direct.push_back(float(p / 18.0 - 1 - 1.0 / 36) * M_PI); 105 | } 106 | } 107 | 108 | float get_theta(float x, float y) 109 | { 110 | if ((x < 0 || x >= m_r) || (y < 0 || y >= m_c)) 111 | return 0; 112 | float dif = m_angle.at(x, y) - m_theta; 113 | return dif > 0 ? dif : dif + 2 * M_PI; 114 | } 115 | 116 | float DB_linear(float x, float y) 117 | { 118 | int xx = int(x), yy = int(y); 119 | float dx1 = x - xx, dx2 = xx + 1 - x; 120 | float dy1 = y - yy, dy2 = yy + 1 - y; 121 | float val = get_theta(xx, yy) * dx2 * dy2 + get_theta(xx + 1, yy) * dx1 * dy2 + get_theta(xx, yy + 1) * dx2 * dy1 + get_theta(xx + 1, yy + 1) * dx1 * dy1; 122 | return val; 123 | } 124 | 125 | std::vector cnt(int x1, int x2, int y1, int y2, int xsign, int ysign) 126 | { 127 | std::vector voting(9); 128 | for (size_t x = x1; x < x2; x++) 129 | { 130 | for (size_t y = y1; y < y2; y++) 131 | { 132 | cv::Mat p = m_H * x * xsign + m_V * y * ysign; 133 | int bin = int((DB_linear(p.at(0, 0) + m_pos.x, p.at(0, 1) + m_pos.y)) / (M_PI / 4) + 1); 134 | if (bin > 8) 135 | bin = 8; 136 | voting[bin] += 1; 137 | } 138 | } 139 | std::vector tmp(8); 140 | std::copy(voting.begin()+1, voting.end(), tmp.begin()); 141 | return tmp; 142 | } 143 | 144 | std::vector get_feature(cv::Point2f pos, float theta) 145 | { 146 | m_pos = pos; 147 | m_theta = theta; 148 | m_H = (cv::Mat_(1, 2) << cos(m_theta), sin(m_theta)); 149 | m_V = (cv::Mat_(1, 2) << -sin(m_theta), cos(m_theta)); 150 | 151 | m_bins = (m_r + m_c) / 150; 152 | std::vector val; 153 | std::vector tmp; 154 | for (int xsign = -1; xsign <= 1; xsign += 2) 155 | { 156 | for (int ysign = -1; ysign <= 1; ysign += 2) 157 | { 158 | tmp = cnt(0, m_bins, 0, m_bins, xsign, ysign); 159 | val.insert(val.end(), tmp.begin(), tmp.end()); 160 | tmp = cnt(m_bins, m_bins * 2, 0, m_bins, xsign, ysign); 161 | val.insert(val.end(), tmp.begin(), tmp.end()); 162 | tmp = cnt(m_bins, m_bins * 2, m_bins, m_bins * 2, xsign, ysign); 163 | val.insert(val.end(), tmp.begin(), tmp.end()); 164 | tmp = cnt(0, m_bins, m_bins, m_bins * 2, xsign, ysign); 165 | val.insert(val.end(), tmp.begin(), tmp.end()); 166 | } 167 | } 168 | return val; 169 | } 170 | 171 | private: 172 | int m_r; 173 | int m_c; 174 | int m_bins; 175 | int m_length; 176 | float m_theta; 177 | cv::Mat m_img; 178 | cv::Mat m_corners; 179 | cv::Mat m_gradient; 180 | cv::Mat m_angle; 181 | cv::Mat m_H; 182 | cv::Mat m_V; 183 | cv::Mat m_feature; 184 | cv::Point2f m_pos; 185 | std::vector m_direct; 186 | }; 187 | 188 | 189 | cv::Mat merge(cv::Mat img1, cv::Mat img2) 190 | { 191 | int h1 = img1.rows, w1 = img1.cols; 192 | int h2 = img2.rows, w2 = img2.cols; 193 | cv::Mat img; 194 | if (h1 < h2) 195 | { 196 | img = cv::Mat::zeros( h2, w1 + w2, CV_8UC3); 197 | cv::Mat roi = img(cv::Rect(0, 0, img1.cols, img1.rows)); 198 | img1.copyTo(roi); 199 | roi = img(cv::Rect(img1.cols, 0, img2.cols, img2.rows)); 200 | img2.copyTo(roi); 201 | } 202 | else if (h1 > h2) 203 | { 204 | img = cv::Mat::zeros(h1, w1 + w2, CV_8UC3); 205 | cv::Mat roi = img(cv::Rect(0, 0, img1.cols, img1.rows)); 206 | img1.copyTo(roi); 207 | roi = img(cv::Rect(img1.cols, 0, img2.cols, img2.rows)); 208 | img2.copyTo(roi); 209 | } 210 | return img; 211 | } 212 | 213 | 214 | int main(int argc, char** argv) 215 | { 216 | cv::Mat src = cv::imread("source.jpg", 1), src_gray; 217 | cv::Mat tgt = cv::imread("target.jpg", 1), tgt_gray; 218 | 219 | cv::cvtColor(src, src_gray, cv::COLOR_BGR2GRAY); 220 | cv::cvtColor(tgt, tgt_gray, cv::COLOR_BGR2GRAY); 221 | 222 | Sift sift_src(src_gray); 223 | Sift sift_tgt(tgt_gray); 224 | 225 | auto [fs ,cs ,ls] = sift_src.get_result(); 226 | auto [ft, ct, lt] = sift_tgt.get_result(); 227 | 228 | cv::Mat img = merge(tgt, src); 229 | 230 | for (size_t i = 0; i < lt; i++) 231 | { 232 | std::vector tmp; 233 | for (size_t j = 0; j < ls; j++) 234 | { 235 | //std::cout << ft.row(i) << std::endl; 236 | //std::cout << fs.row(j) << std::endl; 237 | float sc = (ft.row(i)).dot(fs.row(j)); 238 | tmp.push_back(sc); 239 | } 240 | 241 | int b = std::max_element(tmp.begin(), tmp.end()) - tmp.begin(); 242 | float s = *std::max_element(tmp.begin(), tmp.end()); 243 | 244 | if (s < 0.8) 245 | continue; 246 | 247 | cv::Scalar color(rand() % 255, rand() % 255, rand() % 255); 248 | cv::Point p_start(ct.at(i, 0), ct.at(i, 1)); 249 | cv::Point p_end(cs.at(b, 0) + tgt.cols, cs.at(b, 1)); 250 | cv::line(img, p_start, p_end, color, 1); 251 | } 252 | 253 | cv::imwrite("mysift.jpg", img); 254 | 255 | return EXIT_SUCCESS; 256 | } -------------------------------------------------------------------------------- /skeleton.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 骨架细化算法 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | * @param maxIterations 最大迭代次数 9 | */ 10 | void skeleton(cv::Mat& src, cv::Mat& dst, int maxIterations = -1) 11 | { 12 | dst = src.clone(); 13 | cv::Mat mid = src.clone();; 14 | int count = 0; 15 | while (true) 16 | { 17 | count++; 18 | if (maxIterations != -1 && count > maxIterations) 19 | break; 20 | std::vector mFlag; 21 | for (int i = 0; i < mid.rows; ++i) 22 | { 23 | uchar * p = dst.ptr(i); 24 | for (int j = 0; j < mid.cols; ++j) 25 | { 26 | uchar p1 = p[j]; 27 | if (p1 != 1) continue; 28 | uchar p4 = (j == mid.cols - 1) ? 0 : *(p + j + 1); 29 | uchar p8 = (j == 0) ? 0 : *(p + j - 1); 30 | uchar p2 = (i == 0) ? 0 : *(p - dst.step + j); 31 | uchar p3 = (i == 0 || j == mid.cols - 1) ? 0 : *(p - dst.step + j + 1); 32 | uchar p9 = (i == 0 || j == 0) ? 0 : *(p - dst.step + j - 1); 33 | uchar p6 = (i == mid.rows- 1) ? 0 : *(p + dst.step + j); 34 | uchar p5 = (i == mid.rows- 1 || j == mid.cols - 1) ? 0 : *(p + dst.step + j + 1); 35 | uchar p7 = (i == mid.rows- 1 || j == 0) ? 0 : *(p + dst.step + j - 1); 36 | if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) >= 2 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) <= 6) 37 | { 38 | int ap = 0; 39 | if (p2 == 0 && p3 == 1) ++ap; 40 | if (p3 == 0 && p4 == 1) ++ap; 41 | if (p4 == 0 && p5 == 1) ++ap; 42 | if (p5 == 0 && p6 == 1) ++ap; 43 | if (p6 == 0 && p7 == 1) ++ap; 44 | if (p7 == 0 && p8 == 1) ++ap; 45 | if (p8 == 0 && p9 == 1) ++ap; 46 | if (p9 == 0 && p2 == 1) ++ap; 47 | 48 | if (ap == 1 && p2 * p4 * p6 == 0 && p4 * p6 * p8 == 0) 49 | { 50 | mFlag.push_back(p + j); 51 | } 52 | 53 | } 54 | } 55 | } 56 | 57 | for (std::vector::iterator i = mFlag.begin(); i != mFlag.end(); ++i) 58 | { 59 | **i = 0; 60 | } 61 | 62 | if (mFlag.empty()) 63 | break; 64 | else 65 | mFlag.clear(); 66 | 67 | for (int i = 0; i < mid.rows; ++i) 68 | { 69 | uchar* p = dst.ptr(i); 70 | for (int j = 0; j < mid.cols; ++j) 71 | { 72 | uchar p1 = p[j]; 73 | if (p1 != 1) continue; 74 | uchar p4 = (j == mid.cols - 1) ? 0 : *(p + j + 1); 75 | uchar p8 = (j == 0) ? 0 : *(p + j - 1); 76 | uchar p2 = (i == 0) ? 0 : *(p - dst.step + j); 77 | uchar p3 = (i == 0 || j == mid.cols - 1) ? 0 : *(p - dst.step + j + 1); 78 | uchar p9 = (i == 0 || j == 0) ? 0 : *(p - dst.step + j - 1); 79 | uchar p6 = (i == mid.rows- 1) ? 0 : *(p + dst.step + j); 80 | uchar p5 = (i == mid.rows- 1 || j == mid.cols - 1) ? 0 : *(p + dst.step + j + 1); 81 | uchar p7 = (i == mid.rows- 1 || j == 0) ? 0 : *(p + dst.step + j - 1); 82 | 83 | if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) >= 2 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) <= 6) 84 | { 85 | int ap = 0; 86 | if (p2 == 0 && p3 == 1) ++ap; 87 | if (p3 == 0 && p4 == 1) ++ap; 88 | if (p4 == 0 && p5 == 1) ++ap; 89 | if (p5 == 0 && p6 == 1) ++ap; 90 | if (p6 == 0 && p7 == 1) ++ap; 91 | if (p7 == 0 && p8 == 1) ++ap; 92 | if (p8 == 0 && p9 == 1) ++ap; 93 | if (p9 == 0 && p2 == 1) ++ap; 94 | 95 | if (ap == 1 && p2 * p4 * p8 == 0 && p2 * p6 * p8 == 0) 96 | { 97 | mFlag.push_back(p + j); 98 | } 99 | 100 | } 101 | } 102 | } 103 | 104 | for (std::vector::iterator i = mFlag.begin(); i != mFlag.end(); ++i) 105 | { 106 | **i = 0; 107 | } 108 | 109 | if (mFlag.empty()) 110 | break; 111 | else 112 | mFlag.clear(); 113 | } 114 | 115 | dst *= 255; 116 | } 117 | 118 | int main(int argc, char* argv[]) 119 | { 120 | cv::Mat img = cv::imread("1.jpg", 0), img1, img2 = img.clone(); 121 | cv::cvtColor(img2, img2, cv::COLOR_GRAY2RGB); 122 | cv::threshold(img, img, 100, 1, cv::THRESH_BINARY); 123 | skeleton(img,img1); 124 | 125 | std::vector P; 126 | for (int i = 0; i < img.cols; i++) 127 | for (int j = 0; j < img.rows; j++) 128 | if (img1.at(j, i)>0) 129 | P.push_back(cv::Point(i, j)); 130 | 131 | for (int i = 0; i < P.size(); i++) 132 | cv::circle(img2, cv::Point(P[i].x, P[i].y), 0.5, cv::Scalar(0, 0, 255), -1); 133 | cv::imwrite("skeleton.jpg", img2); 134 | 135 | system("pause"); 136 | return EXIT_SUCCESS; 137 | } 138 | 139 | -------------------------------------------------------------------------------- /sobel.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 计算阶乘 6 | * @param n 自然数 7 | * @return 阶乘 8 | */ 9 | int factorial(int n) 10 | { 11 | int fac = 1; 12 | if (n == 0) return fac; 13 | for (int i = 1; i <= n; ++i) fac *= i; 14 | return fac; 15 | } 16 | 17 | /** 18 | * @description: 获得Sobel平滑算子 19 | * @param size 掩膜大小 20 | * @return Sobel平滑算子 21 | */ 22 | cv::Mat getSobelSmooth(int size) 23 | { 24 | int n = size - 1; 25 | cv::Mat SobelSmoothoper = cv::Mat::zeros(size, 1, CV_32F); 26 | for (int k = 0; k <= n; k++) 27 | { 28 | float *pt = SobelSmoothoper.ptr(0); 29 | pt[k] = factorial(n) / (factorial(k)*factorial(n - k)); 30 | } 31 | return SobelSmoothoper; 32 | } 33 | 34 | /** 35 | * @description: 获得Sobel差分算子 36 | * @param size 掩膜大小 37 | * @return Sobel差分算子 38 | */ 39 | cv::Mat getSobeldiff(int size) 40 | { 41 | cv::Mat Sobeldiffoper = cv::Mat::zeros(cv::Size(size, 1), CV_32F); 42 | cv::Mat SobelSmooth = getSobelSmooth(size - 1); 43 | for (int k = 0; k < size; k++) 44 | { 45 | if (k == 0) 46 | Sobeldiffoper.at(0, k) = 1; 47 | else if (k == size - 1) 48 | Sobeldiffoper.at(0, k) = -1; 49 | else 50 | Sobeldiffoper.at(0, k) = SobelSmooth.at(0, k) - SobelSmooth.at(0, k - 1); 51 | } 52 | return Sobeldiffoper; 53 | } 54 | 55 | /** 56 | * @description: 卷积实现 57 | * @param src 输入图像 58 | * @param dst 输出图像 59 | * @param kernel 卷积核 60 | */ 61 | void conv2D(cv::Mat& src, cv::Mat& dst, cv::Mat kernel) 62 | { 63 | cv::flip(kernel, kernel, -1); 64 | cv::filter2D(src, dst, src.depth(), kernel); 65 | } 66 | 67 | /** 68 | * @description: 可分离卷积———先水平方向卷积,后垂直方向卷积 69 | * @param src 输入图像 70 | * @param dst 输出图像 71 | * @param kernel_X x方向卷积 72 | * @param kernel_Y y方向卷积 73 | */ 74 | void sepConv2D_X_Y(cv::Mat& src, cv::Mat& dst, cv::Mat kernel_X, cv::Mat kernel_Y) 75 | { 76 | cv::Mat dst_kernel_X; 77 | conv2D(src, dst_kernel_X, kernel_X); 78 | conv2D(dst_kernel_X, dst, kernel_Y); 79 | } 80 | 81 | /** 82 | * @description: 可分离卷积———先垂直方向卷积,后水平方向卷积 83 | * @param src 输入图像 84 | * @param dst 输出图像 85 | * @param kernel_Y y方向卷积 86 | * @param kernel_X x方向卷积 87 | */ 88 | void sepConv2D_Y_X(cv::Mat& src, cv::Mat& dst, cv::Mat kernel_Y, cv::Mat kernel_X) 89 | { 90 | cv::Mat dst_kernel_Y; 91 | conv2D(src, dst_kernel_Y, kernel_Y); 92 | conv2D(dst_kernel_Y, dst, kernel_X); 93 | } 94 | 95 | /** 96 | * @description: Sobel算子边缘检测 97 | * @param src 输入图像 98 | * @param dst 输出图像 99 | * @param size 掩膜大小 100 | */ 101 | void sobel(cv::Mat& src, cv::Mat& dst, int size) 102 | { 103 | cv::Mat SobelSmoothoper = getSobelSmooth(size); 104 | cv::Mat Sobeldiffoper = getSobeldiff(size); 105 | cv::Mat dst_X, dst_Y; 106 | 107 | sepConv2D_X_Y(src, dst_Y, SobelSmoothoper, Sobeldiffoper.t()); 108 | sepConv2D_Y_X(src, dst_X, SobelSmoothoper.t(), Sobeldiffoper); 109 | 110 | dst = abs(dst_X) + abs(dst_Y); 111 | cv::convertScaleAbs(dst, dst); 112 | cv::convertScaleAbs(dst_X, dst_X); 113 | cv::convertScaleAbs(dst_Y, dst_Y); 114 | } 115 | 116 | int main(int argc, char* argv[]) 117 | { 118 | cv::Mat src = cv::imread("1.jpg", 0), dst; 119 | 120 | sobel(src, dst, 3); 121 | cv::imwrite("sobel.jpg", dst); 122 | 123 | system("pause"); 124 | return EXIT_SUCCESS; 125 | } 126 | -------------------------------------------------------------------------------- /susan.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | void susan(cv::Mat& src, cv::Mat& dst, float t) 8 | { 9 | cv::Mat susan_mask = cv::Mat::ones(7, 7, CV_8U); 10 | susan_mask.at(0, 0) = 0; 11 | susan_mask.at(0, 1) = 0; 12 | susan_mask.at(0, 5) = 0; 13 | susan_mask.at(0, 6) = 0; 14 | susan_mask.at(1, 0) = 0; 15 | susan_mask.at(1, 6) = 0; 16 | susan_mask.at(5, 0) = 0; 17 | susan_mask.at(5, 6) = 0; 18 | susan_mask.at(6, 0) = 0; 19 | susan_mask.at(6, 1) = 0; 20 | susan_mask.at(6, 5) = 0; 21 | susan_mask.at(6, 6) = 0; 22 | 23 | //for (size_t i = 0; i < susan_mask.rows; i++) 24 | //{ 25 | // for (size_t j = 0; j < susan_mask.cols; j++) 26 | // { 27 | // std::cout << (int)susan_mask.at(i, j) << " "; 28 | // } 29 | // std::cout << std::endl; 30 | //} 31 | 32 | int row_s = 3, col_s = 3; 33 | int row_e = src.rows - 3, col_e = src.cols - 3; 34 | float n_max = 0; 35 | cv::Mat n_arr = 37 * cv::Mat::ones(src.size(), CV_8U); 36 | 37 | for (size_t i = row_s; i < row_e; i++) 38 | { 39 | for (size_t j = col_s; j < col_e; j++) 40 | { 41 | cv::Mat susan_zone = src(cv::Rect(j - 3, i - 3, 7, 7)); 42 | //for (size_t i = 0; i < susan_zone.rows; i++) 43 | //{ 44 | // for (size_t j = 0; j < susan_zone.cols; j++) 45 | // { 46 | // std::cout << (int)susan_zone.at(i, j) << " "; 47 | // } 48 | // std::cout << std::endl; 49 | //} 50 | 51 | std::vector susan_zone_vec; 52 | for (size_t m = 0; m < susan_mask.rows; m++) 53 | { 54 | for (size_t n = 0; n < susan_mask.cols; n++) 55 | { 56 | if ((int)susan_mask.at(m, n) != 0) 57 | susan_zone_vec.push_back((int)susan_zone.at(m, n)); 58 | } 59 | } 60 | 61 | //for (size_t k = 0; k < susan_zone_vec.size(); k++) 62 | //{ 63 | // std::cout << k << " " << susan_zone_vec[k] << std::endl; 64 | //} 65 | 66 | float r0 = src.at(i, j); 67 | //std::cout << i << " " << j << " " << r0 << std::endl; 68 | 69 | std::vector similarity(37); 70 | for (size_t k = 0; k < similarity.size(); k++) 71 | { 72 | similarity[k] = exp(-pow((1.0 * susan_zone_vec[k] - r0) / t, 6)); 73 | //std::cout << similarity[k] << std::endl; 74 | } 75 | float n = std::accumulate(similarity.begin(), similarity.end(), 0.0f); 76 | //std::cout << i << " " << j << " " << n << std::endl; 77 | 78 | if (n > n_max) 79 | n_max = n; 80 | 81 | n_arr.at(i, j) = n; 82 | } 83 | } 84 | 85 | float g = n_max / 2; 86 | //std::cout << g << std::endl; 87 | 88 | cv::Mat R = cv::Mat::zeros(src.size(), CV_8U); 89 | dst = src.clone(); 90 | cv::cvtColor(dst, dst, cv::COLOR_GRAY2BGR); 91 | for (size_t i = 0; i < R.rows; i++) 92 | { 93 | for (size_t j = 0; j < R.cols; j++) 94 | { 95 | if (n_arr.at(i, j) < g) 96 | //std::cout << i << " " << j << " " << n_arr.at(i, j) << " " << g << std::endl; 97 | R.at(i, j) = g - n_arr.at(i, j); 98 | if (R.at(i, j) > 0) 99 | dst.at(i, j) = cv::Vec3b(0, 0, 255); 100 | } 101 | } 102 | 103 | #ifdef GRAVITY_FITER 104 | std::vector> x_label(7, std::vector(7)); 105 | std::vector> y_label(7, std::vector(7)); 106 | for (size_t i = 0; i < 7; i++) 107 | { 108 | for (size_t j = 0; j < 7; j++) 109 | { 110 | x_label[i][j] = j - 3; 111 | y_label[j][i] = j - 3; 112 | } 113 | } 114 | 115 | for (size_t i = row_s; i < row_e; i++) 116 | { 117 | for (size_t j = col_s; j < col_e; j++) 118 | { 119 | if (R.at(i, j) == 0) 120 | continue; 121 | 122 | cv::Mat susan_zone = src(cv::Rect(j - 3, i - 3, 7, 7)); 123 | 124 | float r0 = src.at(i, j); 125 | 126 | std::vector> similarity(7, std::vector(7)); 127 | for (size_t m = 0; m < similarity.size(); m++) 128 | { 129 | for (size_t n = 0; n < similarity[0].size(); n++) 130 | { 131 | similarity[m][n] = exp(-pow((1.0 * (int)susan_zone.at(m, n) - r0) / t, 6)); 132 | //std::cout << similarity[m][n] << " "; 133 | } 134 | //std::cout << std::endl; 135 | } 136 | //std::cout << std::endl; 137 | 138 | float sum = 0.0f; 139 | float sum_x = 0.0f; 140 | float sum_y = 0.0f; 141 | for (size_t m = 0; m < similarity.size(); m++) 142 | { 143 | for (size_t n = 0; n < similarity[0].size(); n++) 144 | { 145 | if ((int)susan_mask.at(m, n) == 1) 146 | { 147 | sum += similarity[m][n]; 148 | sum_x += similarity[m][n] * x_label[m][n]; 149 | sum_y += similarity[m][n] * y_label[m][n]; 150 | } 151 | } 152 | } 153 | float g_x = sum_x / sum; 154 | float g_y = sum_y / sum; 155 | float distance = sqrt(g_x * g_x + g_y * g_y); 156 | 157 | float F = 1.5; 158 | if (distance < F) 159 | R.at(i, j) = 0; 160 | } 161 | } 162 | 163 | dst = src.clone(); 164 | cv::cvtColor(dst, dst, cv::COLOR_GRAY2BGR); 165 | for (size_t i = 0; i < R.rows; i++) 166 | { 167 | for (size_t j = 0; j < R.cols; j++) 168 | { 169 | if (R.at(i, j)) 170 | dst.at(i, j) = cv::Vec3b(0, 0, 255); 171 | } 172 | } 173 | #endif // GRAVITY_FITER 174 | } 175 | 176 | 177 | int main(int argc, char** argv) 178 | { 179 | cv::Mat src = cv::imread("1.png", 0), dst; 180 | 181 | susan(src, dst, 10.0f); 182 | cv::imwrite("susan.jpg", dst); 183 | 184 | system("pause"); 185 | return EXIT_SUCCESS; 186 | } 187 | 188 | -------------------------------------------------------------------------------- /tophat.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * @description: 顶帽运算 6 | * @param src 输入图像 7 | * @param dst 输出图像 8 | * @param size 掩膜大小 9 | */ 10 | void tophat(cv::Mat& src, cv::Mat& dst, cv::Size size) 11 | { 12 | cv::Mat element = getStructuringElement(cv::MORPH_RECT, size); 13 | cv::morphologyEx(src, dst, cv::MORPH_OPEN, element); 14 | dst = src - dst; 15 | } 16 | 17 | int main(int argc, char* argv[]) 18 | { 19 | cv::Mat src = cv::imread("1.jpg", 0), dst; 20 | 21 | tophat(src, dst, cv::Size(3, 3)); 22 | cv::imwrite("tophat.jpg", dst); 23 | 24 | system("pause"); 25 | return EXIT_SUCCESS; 26 | } 27 | 28 | --------------------------------------------------------------------------------