diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..835d40b --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.jpg +*.png +*.tif +*.bmp +*.avif +IRImageProcessing/output/ +.vs/ diff --git a/IRImageProcessing.sln b/IRImageProcessing.sln new file mode 100644 index 0000000..df21926 --- /dev/null +++ b/IRImageProcessing.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34525.116 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IRImageProcessing", "IRImageProcessing\IRImageProcessing.vcxproj", "{D48B5F5F-E967-4A6D-A6FE-EFE946014037}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D48B5F5F-E967-4A6D-A6FE-EFE946014037}.Debug|x64.ActiveCfg = Debug|x64 + {D48B5F5F-E967-4A6D-A6FE-EFE946014037}.Debug|x64.Build.0 = Debug|x64 + {D48B5F5F-E967-4A6D-A6FE-EFE946014037}.Debug|x86.ActiveCfg = Debug|Win32 + {D48B5F5F-E967-4A6D-A6FE-EFE946014037}.Debug|x86.Build.0 = Debug|Win32 + {D48B5F5F-E967-4A6D-A6FE-EFE946014037}.Release|x64.ActiveCfg = Release|x64 + {D48B5F5F-E967-4A6D-A6FE-EFE946014037}.Release|x64.Build.0 = Release|x64 + {D48B5F5F-E967-4A6D-A6FE-EFE946014037}.Release|x86.ActiveCfg = Release|Win32 + {D48B5F5F-E967-4A6D-A6FE-EFE946014037}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8EE5FA51-A4CB-4678-A0B9-227203EAAF28} + EndGlobalSection +EndGlobal diff --git a/IRImageProcessing/IRImageProcessing.vcxproj b/IRImageProcessing/IRImageProcessing.vcxproj new file mode 100644 index 0000000..a6163aa --- /dev/null +++ b/IRImageProcessing/IRImageProcessing.vcxproj @@ -0,0 +1,136 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {D48B5F5F-E967-4A6D-A6FE-EFE946014037} + RemoveArea + 10.0 + + + + Application + true + v143 + MultiByte + + + Application + false + v143 + true + MultiByte + + + Application + true + v143 + MultiByte + + + Application + false + v143 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + D:\SDK\opencv-4.0.0\build\install\include;$(IncludePath) + D:\SDK\opencv-4.0.0\build\install\x64\vc15\lib;$(LibraryPath) + + + D:\SDK\opencv-4.0.0\build\install\include;$(IncludePath) + D:\SDK\opencv-4.0.0\build\install\x64\vc15\lib;$(LibraryPath) + + + + Level3 + Disabled + true + true + + + + + Level3 + Disabled + true + true + stdcpp17 + + + + + Level3 + MaxSpeed + true + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + true + stdcpp17 + + + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/IRImageProcessing/Source.cpp b/IRImageProcessing/Source.cpp new file mode 100644 index 0000000..7577c73 --- /dev/null +++ b/IRImageProcessing/Source.cpp @@ -0,0 +1,318 @@ +#include "myOpenCV3.h" +#include +#include +#include +#include + +void thinningIteration(cv::Mat& img, int iteration) { + cv::Mat marker = cv::Mat::ones(img.size(), CV_8UC1); + + for (int y = 1; y < img.rows - 1; ++y) { + for (int x = 1; x < img.cols - 1; ++x) { + uchar p2 = img.at(y - 1, x); + uchar p3 = img.at(y - 1, x + 1); + uchar p4 = img.at(y, x + 1); + uchar p5 = img.at(y + 1, x + 1); + uchar p6 = img.at(y + 1, x); + uchar p7 = img.at(y + 1, x - 1); + uchar p8 = img.at(y, x - 1); + uchar p9 = img.at(y - 1, x - 1); + + int C = (!p2 & (p3 | p4)) + (!p4 & (p5 | p6)) + + (!p6 & (p7 | p8)) + (!p8 & (p9 | p2)); + int N1 = (p9 | p2) + (p3 | p4) + (p5 | p6) + (p7 | p8); + int N2 = (p2 | p3) + (p4 | p5) + (p6 | p7) + (p8 | p9); + int N = N1 < 3 ? N1 : N2; + int m = iteration == 0 ? ((p6 | p7 | (!p9)) & p8) : ((p2 | p3 | (!p5)) & p4); + + if (C == 1 && (N >= 2 && N <= 3) & m == 0) + marker.at(y, x) = 0; + } + } + img &= marker; +} + +void thinning(const cv::Mat& src, cv::Mat& dst) { + dst = src.clone(); + dst /= 255; + // ���K�� + cv::Mat normalizedImage; + cv::normalize(src, normalizedImage, 0, 1, cv::NORM_MINMAX, CV_32F); + cv::Mat prev = cv::Mat::zeros(dst.size(), CV_8UC1); + cv::Mat diff; + + do { + thinningIteration(dst, 0); + thinningIteration(dst, 1); + cv::absdiff(dst, prev, diff); + dst.copyTo(prev); + } while (cv::countNonZero(diff) > 0); + dst *= 255; +} +std::vector findBranchPoints(cv::Mat& img) +{ + std::vector branchPoints; + + for (int y = 1; y < img.rows - 1; ++y) + { + for (int x = 1; x < img.cols - 1; ++x) + { + // �摜�����i�܂��͍��j�łȂ��ꍇ�͖��� + if (img.at(y, x) == 255) continue; + + // 8�ߖT�̔��i�܂��͍��j�s�N�Z���̐����J�E���g + int count = 0; + if (img.at(y - 1, x - 1) > 0) ++count; + if (img.at(y - 1, x) > 0) ++count; + if (img.at(y - 1, x + 1) > 0) ++count; + if (img.at(y, x - 1) > 0) ++count; + if (img.at(y, x + 1) > 0) ++count; + if (img.at(y + 1, x - 1) > 0) ++count; + if (img.at(y + 1, x) > 0) ++count; + if (img.at(y + 1, x + 1) > 0) ++count; + + // ���i�܂��͍��j�s�N�Z����3�ˆȏ゠��ꍇ�͕���_�Ƃ��ċL�^ + if (count >= 3) + branchPoints.push_back(cv::Point(x, y)); + } + } + + return branchPoints; +} + +std::vector extractBifurcationPoints(cv::Mat& thinnedImage) { + int rows = thinnedImage.rows; + int cols = thinnedImage.cols; + int neighbor[2][8] = { {-1, -1, 0, 1, 1, 1, 0, -1}, {0, 1, 1, 1, 0, -1, -1, -1} }; + std::vector bifurcationPoints; + + for (int i = 1; i < rows - 1; i++) { + for (int j = 1; j < cols - 1; j++) { + if (thinnedImage.at(i, j) == 255) { + int transitions = 0; + int neighborCount = 0; + + for (int k = 0; k < 8; k++) { + int x = i + neighbor[0][k]; + int y = j + neighbor[1][k]; + + int nextX = i + neighbor[0][(k + 1) % 8]; + int nextY = j + neighbor[1][(k + 1) % 8]; + + if (thinnedImage.at(x, y) == 255) { + neighborCount++; + + if (thinnedImage.at(nextX, nextY) == 0) + transitions++; + } + } + + if (transitions == 1 && neighborCount == 3) + bifurcationPoints.push_back(cv::Point(j, i)); // OpenCV�ł́Ax���W����ԍ��Ay���W���s�ԍ��ɑΉ����܂��B + } + } + } + + return bifurcationPoints; +} + +void BinaryProcessing(const cv::Mat& ori, const cv::Mat& src, std::string dirName) +{ + // ��Â̓�l�� + cv::Mat otsuBinaryImage; + cv::threshold(src, otsuBinaryImage, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU); + // �K���I��l�� + cv::Mat adaptiveBinaryImage; + cv::adaptiveThreshold(src, adaptiveBinaryImage, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY_INV, 41, 10); + + // �����t�H�W�[�ϊ��p�̃J�[�l�� + cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)); + // �����t�H���W�[�ϊ� + cv::Mat morphologyImage; + //cv::morphologyEx(adaptiveBinaryImage, morphologyImage, cv::MORPH_OPEN, element); + cv::morphologyEx(adaptiveBinaryImage, morphologyImage, cv::MORPH_OPEN, element); + //cv::dilate(binaryImage, dilatedImage, cv::Mat(), cv::Point(-1, -1), 1); // 1��c�������܂��B�K�v�ɉ����Ă��̒l��ύX���Ă��������B + + cv::Mat borderRemoved = morphologyImage(cv::Rect(10, 10, morphologyImage.cols - 20, morphologyImage.rows - 20)); + cv::Mat borderAdded; + cv::copyMakeBorder(borderRemoved, borderAdded, 10, 10, 10, 10, cv::BORDER_CONSTANT, 255); + + cv::Mat invImage; + //cv::bitwise_not(morphologyImage, invImage); + //cv::bitwise_not(dilatedImage, invImage); + // �א��� + cv::Mat thinnedImage; + thinning(morphologyImage, thinnedImage); + + + cv::Mat kernel1 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)); + //cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + //cv::dilate(thinnedImage, thinnedImage, kernel1, cv::Point(-1, -1), 1); + // �����t�H���W�[�ϊ� + + //cv::morphologyEx(thinnedImage, thinnedImage, cv::MORPH_CLOSE, element); + + // �א����摜���ēx�c�� + cv::Mat outputImage; + cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); + cv::dilate(thinnedImage, outputImage, kernel, cv::Point(-1, -1), 2); + //cv::bitwise_not(thinnedImage, thinnedImage); + + + + cv::bitwise_not(adaptiveBinaryImage, adaptiveBinaryImage); + cv::bitwise_not(morphologyImage, morphologyImage); + cv::bitwise_not(outputImage, outputImage); + cv::bitwise_not(thinnedImage, thinnedImage); + + + cv::imwrite(dirName + "/OtsuBinaryImage.png", otsuBinaryImage); + cv::imwrite(dirName + "/AdaptiveBinary.png", adaptiveBinaryImage); + cv::imwrite(dirName + "/Morpho.png", morphologyImage); + cv::imwrite(dirName + "/Thinnig.png", thinnedImage); + cv::imwrite(dirName + "/DilatedThinning.png", outputImage); + + + cv::Mat circleImage; + ori.convertTo(circleImage, CV_8U); + cv::Mat circleImageRGB; + cv::cvtColor(circleImage, circleImageRGB, cv::COLOR_GRAY2BGR); // �O���[�X�P�[������RGB�֕ϊ� + + std::vector branchPoints = extractBifurcationPoints(thinnedImage); // ����_�����o + + // ����_�ɉ~��`�� + for (const auto& point : branchPoints) { + cv::circle(circleImageRGB, point, 10, cv::Scalar(0, 0, 255), 2); // ���a3�̉~��ԐF�ŕ`�悵�܂� + } + + cv::imwrite(dirName + "/Circle.png", circleImageRGB); + +} + +void WindowProcessing(const cv::Mat& src16U, cv::Mat& dst8U, double limit, std::string dirName) +{ + + + double amin, amax; + cv::minMaxLoc(src16U, &amin, &amax); // �摜�̍ŏ��l�ƍő�l���擾 + + double scale = limit / (amax - amin); // �X�P�[�����O�W�����v�Z + + src16U.convertTo(dst8U, CV_8U, scale, -amin * scale); + //cv::imwrite(dirName + "/Windowed_2.png", dst8U); +} + +void GaborProcessing(const cv::Mat& ori, cv::Mat& src, std::string dirName) +{ + + int division = 16; + int ksize = 17; + double sigma = 5; + double theta; + double lambda = 16; + double gamma = 1; + double psi = 0; + double angle = 0; + + cv::Mat maxGaborImage; + double maxGaborSum = -1.0; + int maxAngle = -1; + cv::Mat src32F; + src.convertTo(src32F, CV_64F); + cv::Mat margeImage = cv::Mat::zeros(src.size(), CV_8U); + + // Find the angle that gives the maximum sum of gaborImage8U + for (int i = 0; i < division; i++, angle += (180 / division)) { + theta = angle * CV_PI / 180.0; + // opencv��gabor filter + cv::Mat kern = cv::getGaborKernel(cv::Size(ksize, ksize), sigma, theta, lambda, gamma, psi, CV_64F); + kern /= cv::sum(kern)[0]; + + + cv::Mat gaborImage, gabor8UImage, gaborOtsuBinaryImage; + cv::filter2D(src, gaborImage, CV_64F, kern); + gaborImage.convertTo(gabor8UImage, CV_8U); + cv::threshold(gabor8UImage, gaborOtsuBinaryImage, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU); + + + cv::Mat gaborImageScaled, diffImage; + + // �����摜 + cv::absdiff(src, gabor8UImage, diffImage); + cv::convertScaleAbs(diffImage, gaborImageScaled, 1.0 / division); + cv::imwrite(dirName + "/Gabor_" + std::to_string(angle) + ".png", gabor8UImage); + cv::imwrite(dirName + "/diff_" + std::to_string(angle) + ".png", diffImage); + cv::imwrite(dirName + "/GaborOtsuBinaryImage_" + std::to_string(angle) + ".png", gaborOtsuBinaryImage); + cv::add(margeImage, gaborImageScaled, margeImage, cv::noArray(), CV_8U); + + + } + + cv::Mat margeOtsuBinaryImage; + cv::threshold(margeImage, margeOtsuBinaryImage, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU); + cv::imwrite(dirName + "/MargeOtsuBinaryImage.png", margeOtsuBinaryImage); + cv::imwrite(dirName + "/Marge.png", margeImage); + BinaryProcessing(ori, margeImage, dirName); + +} + + + + +int main() { + std::string inputFileName = "trimmed.tif"; + + // �o�͏��� + std::string baseDir = "output/"; + std::string dirBaseName = "sigma5_lambda16"; + std::string dirName = baseDir + dirBaseName; + + + // output�f�B���N�g�������݂��Ȃ��ꍇ�͍쐬 + if (!std::filesystem::exists(baseDir)) { + std::filesystem::create_directory(baseDir); + } + + int dirCount = 2; + // �w�肳�ꂽ�f�B���N�g�������݂���ꍇ�́A�V�������O�𐶐� + while (std::filesystem::exists(dirName)) { + dirName = baseDir + dirBaseName + std::to_string(dirCount); + ++dirCount; + } + + std::filesystem::create_directory(dirName); + + cv::Mat image = cv::imread(inputFileName, cv::IMREAD_ANYDEPTH); + + // �K������ + cv::Mat windowedImage; + WindowProcessing(image, windowedImage, 255.0, dirName); + + // �m�C�Y���� + cv::Mat gaussinaBlurImage; + cv::GaussianBlur(windowedImage, gaussinaBlurImage, cv::Size(3, 3), 9, 0); + + // CLAHE��p�����q�X�g�O�������R�� + cv::Ptr clahe = cv::createCLAHE(10.0, cv::Size(16, 16)); + cv::Mat claheImage; + clahe->apply(windowedImage, claheImage); + + // �R���g���X�g���� + cv::Mat claheOtsuBinaryImage; + cv::threshold(claheImage, claheOtsuBinaryImage, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU); + + //BinaryProcessing(windowedImage, claheImage, dirName); + + // �K�{�[���t�B���^ + GaborProcessing(windowedImage, claheImage, dirName); + + + cv::imwrite(dirName + "/Original.tif", image); + cv::imwrite(dirName + "/WindowedImage.png", windowedImage); + cv::imwrite(dirName + "/Gaussian.png", gaussinaBlurImage); + cv::imwrite(dirName + "/CLAHE.png", claheImage); + cv::imwrite(dirName + "/CLAHEOtsu.png", claheOtsuBinaryImage); + + return 0; +} + diff --git a/IRImageProcessing/myOpenCV3.h b/IRImageProcessing/myOpenCV3.h new file mode 100644 index 0000000..60ad8df --- /dev/null +++ b/IRImageProcessing/myOpenCV3.h @@ -0,0 +1,76 @@ + +// OpenCV 3�n ���ʃw�b�_�[�t�@�C�� +// T.Nakaguchi + +// �w�b�_�[�t�@�C�� +#pragma warning(disable: 4819) +#include +#pragma warning(default: 4819) + +// �o�[�W�����擾 +#define CV_VERSION_STR CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION) + +// �r���h���[�h +#ifdef _DEBUG +#define CV_EXT_STR "d.lib" +#else +#define CV_EXT_STR ".lib" +#endif + +// ���C�u�����̃����N�i�s�v�ȕ��̓R�����g�A�E�g�j +#define PRE_COMPILE 0 // �C���X�g�[���łȂ� 1 �•ʃ��C�u�����g�p���� 0 +#define PREHEAD "opencv_" + +#if PRE_COMPILE +// OpenCV3.0 �C���X�g�[���� +#pragma comment(lib, PREHEAD "world" CV_VERSION_STR CV_EXT_STR) // �S�� +#pragma comment(lib, PREHEAD "ts" CV_VERSION_STR CV_EXT_STR) // �f���֘A + +#else +// �•ʂ̃��C�u�����w�� �iCmake��Static�Ŏg�p���Ȃǁj +// ��{���W���[�� +#pragma comment(lib, PREHEAD "core" CV_VERSION_STR CV_EXT_STR) // ��{�@�\ +#pragma comment(lib, PREHEAD "imgproc" CV_VERSION_STR CV_EXT_STR) // �摜���� +#pragma comment(lib, PREHEAD "imgcodecs" CV_VERSION_STR CV_EXT_STR) // �摜�t�@�C�����o�� +#pragma comment(lib, PREHEAD "videoio" CV_VERSION_STR CV_EXT_STR) // ����t�@�C�����o�� +#pragma comment(lib, PREHEAD "highgui" CV_VERSION_STR CV_EXT_STR) // ���@�\GUI +#pragma comment(lib, PREHEAD "video" CV_VERSION_STR CV_EXT_STR) // ���摜��� +#pragma comment(lib, PREHEAD "calib3d" CV_VERSION_STR CV_EXT_STR) // �J�����Z���ƎO�����č\�z +#pragma comment(lib, PREHEAD "features2d" CV_VERSION_STR CV_EXT_STR) // �摜������� +#pragma comment(lib, PREHEAD "objdetect" CV_VERSION_STR CV_EXT_STR) // ���̌��o +#pragma comment(lib, PREHEAD "ml" CV_VERSION_STR CV_EXT_STR) // �@�B�w�K +#pragma comment(lib, PREHEAD "flann" CV_VERSION_STR CV_EXT_STR) // �������N���X�^�����O�ƌ��� +#pragma comment(lib, PREHEAD "photo" CV_VERSION_STR CV_EXT_STR) // �v�Z�@�ʐ^ +#pragma comment(lib, PREHEAD "stitching" CV_VERSION_STR CV_EXT_STR) // �摜�ڑ� +//#pragma comment(lib, PREHEAD "hal" CV_VERSION_STR CV_EXT_STR) // �n�[�h�E�F�A������ +#pragma comment(lib, PREHEAD "shape" CV_VERSION_STR CV_EXT_STR) // �`���v���o +#pragma comment(lib, PREHEAD "superres" CV_VERSION_STR CV_EXT_STR) // ���� +#pragma comment(lib, PREHEAD "videostab" CV_VERSION_STR CV_EXT_STR) // ���摜���艻 +//#pragma comment(lib, PREHEAD "vis" CV_VERSION_STR CV_EXT_STR) // 3�����Ž��� + +// �g�����W���[�� +//#pragma comment(lib, PREHEAD "adas" CV_VERSION_STR CV_EXT_STR) // ��i�I�f�o�C�X�T�|�[�g +//#pragma comment(lib, PREHEAD "aruco" CV_VERSION_STR CV_EXT_STR) // AR�p�}�[�J�[ +#pragma comment(lib, PREHEAD "bgsegm" CV_VERSION_STR CV_EXT_STR) // ���nj^�w�i�E�O�i���� +#pragma comment(lib, PREHEAD "bioinspired" CV_VERSION_STR CV_EXT_STR) // ���̂Ɋ�Â����o�I���� +#pragma comment(lib, PREHEAD "ccalib" CV_VERSION_STR CV_EXT_STR) // �J�X�^���p�^�[���ɂ��J�����Z���ƎO�����č\�� +//#pragma comment(lib, PREHEAD "cvv" CV_VERSION_STR CV_EXT_STR) // �Θb�I���o�I�f�o�b�OGUI +#pragma comment(lib, PREHEAD "datasets" CV_VERSION_STR CV_EXT_STR) // ����f�[�^�Z�b�g��舵���t���[�����[�N +#pragma comment(lib, PREHEAD "face" CV_VERSION_STR CV_EXT_STR) // ��F�� +//#pragma comment(lib, PREHEAD "latentsvm" CV_VERSION_STR CV_EXT_STR) // Latent-SVM +#pragma comment(lib, PREHEAD "line_descriptor" CV_VERSION_STR CV_EXT_STR) // �����o�̃o�C�i���\�� +//#pragma comment(lib, PREHEAD "matlab" CV_VERSION_STR CV_EXT_STR) // MATLAB�u���b�W +#pragma comment(lib, PREHEAD "optflow" CV_VERSION_STR CV_EXT_STR) // �I�v�e�B�J���t���[ +#pragma comment(lib, PREHEAD "reg" CV_VERSION_STR CV_EXT_STR) // �摜�ʒu���킹 +#pragma comment(lib, PREHEAD "rgbd" CV_VERSION_STR CV_EXT_STR) // RGB-�[�x�J���� +#pragma comment(lib, PREHEAD "saliency" CV_VERSION_STR CV_EXT_STR) // �摜 ������ API +#pragma comment(lib, PREHEAD "surface_matching" CV_VERSION_STR CV_EXT_STR) // �\�ʃ��f����v���o +#pragma comment(lib, PREHEAD "text" CV_VERSION_STR CV_EXT_STR) // �V�[���������o�ƔF�� +#pragma comment(lib, PREHEAD "tracking" CV_VERSION_STR CV_EXT_STR) // �ǐ� +#pragma comment(lib, PREHEAD "xfeatures2d" CV_VERSION_STR CV_EXT_STR) // �g���� �摜������� +#pragma comment(lib, PREHEAD "ximgproc" CV_VERSION_STR CV_EXT_STR) // �g���� �摜���� +#pragma comment(lib, PREHEAD "xobjdetect" CV_VERSION_STR CV_EXT_STR) // �g���� ���̌��o +#pragma comment(lib, PREHEAD "xphoto" CV_VERSION_STR CV_EXT_STR) // �g���� �v�Z�@�ʐ^ +#endif + +using namespace cv; diff --git a/IRImageProcessing/source.h b/IRImageProcessing/source.h new file mode 100644 index 0000000..782b2dd --- /dev/null +++ b/IRImageProcessing/source.h @@ -0,0 +1,8 @@ +#pragma + + +Mat src_img; +Mat change; + +Point Cancer_centroid_point; +Rect cancer_roi; \ No newline at end of file