123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630 |
- // cv.cpp : 定义 DLL 的导出函数。
- //
- #include "stdafx.h"
- #include "framework.h"
- #include "cv.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
- #ifdef _DEBUG
- extern void test();
- #endif
- // 唯一的应用程序对象
- CWinApp theApp;
- using namespace std;
- int main()
- {
- int nRetCode = 0;
- HMODULE hModule = ::GetModuleHandle(nullptr);
- if (hModule != nullptr)
- {
- // 初始化 MFC 并在失败时显示错误
- if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0))
- {
- // TODO: 在此处为应用程序的行为编写代码。
- _tprintf(_T("错误: MFC 初始化失败\n"));
- nRetCode = 1;
- }
- else
- {
- // TODO: 在此处为应用程序的行为编写代码。
- #ifdef _DEBUG
- test();
- #endif
- }
- }
- else
- {
- // TODO: 更改错误代码以符合需要
- _tprintf(_T("错误: GetModuleHandle 失败\n"));
- nRetCode = 1;
- }
- return nRetCode;
- }
- CV_API bool ReadImage(std::string strImgPath, cv::Mat& img)
- {
- // 参数有效性判断;
- if (!PathFileExists(strImgPath.c_str())) {
- #ifdef _DEBUG
- OutputDebugString("参数无效!");
- #endif
- return false;
- }
- // 以BGR三通道方式读取图片;
- img = cv::imread(strImgPath.c_str(), cv::IMREAD_COLOR);
- // 判断图片是否为空;
- if (img.empty()) {
- #ifdef _DEBUG
- OutputDebugString("读取图片失败!");
- #endif
- return false;
- }
- return true;
- }
- CV_API bool GetBinaryImage(std::string strImgPath, long nThresholdVal, long nMaxThresholdVal, cv::Mat& thresholdImg)
- {
- cv::Mat img;
- // 读取图片;
- if (!ReadImage(strImgPath, img))
- return false;
- cv::Mat grayImg;
- // 转成灰阶图;
- cv::cvtColor(img, grayImg, cv::COLOR_BGR2GRAY);
- // 释放对象;
- img.release();
- cv::Mat gaussImg;
- // 再高斯模糊处理(滤波);
- cv::GaussianBlur(grayImg, gaussImg, cv::Size(5, 5), 0, 0);
- // 释放对象;
- grayImg.release();
- // 全局化指定的阀值与返回值相等;
- cv::threshold(gaussImg, thresholdImg, nThresholdVal, nMaxThresholdVal, cv::THRESH_BINARY);
- // 释放对象;
- gaussImg.release();
- // 判断图片是否空;
- if (thresholdImg.empty())
- return false;
- return true;
- }
- CV_API bool GetOTSUBinaryImage(std::string strImgPath, long nThresholdVal, long nMaxThresholdVal, cv::Mat& thresholdImg)
- {
- cv::Mat img;
- // 读取图片;
- if (!ReadImage(strImgPath, img))
- return false;
- cv::Mat grayImg;
- // 转成灰阶图;
- cv::cvtColor(img, grayImg, cv::COLOR_BGR2GRAY);
- // 释放对象;
- img.release();
- cv::Mat gaussImg;
- // 再高斯模糊处理(滤波);
- cv::GaussianBlur(grayImg, gaussImg, cv::Size(5, 5), 0, 0);
- // 释放对象;
- grayImg.release();
- // OTSU,此时参数3可随意设置;
- cv::threshold(gaussImg, thresholdImg, nThresholdVal, nMaxThresholdVal, cv::THRESH_BINARY | cv::THRESH_OTSU);
- // 释放对象;
- gaussImg.release();
- // 判断图片是否空;
- if (thresholdImg.empty())
- return false;
- return true;
- }
- CV_API bool GetAdaptiveBinaryImage(std::string strImgPath, long nMaxThresholdVal, cv::Mat& thresholdImg)
- {
- cv::Mat img;
- // 读取图片;
- if (!ReadImage(strImgPath, img))
- return false;
- cv::Mat grayImg;
- // 转成灰阶图;
- cv::cvtColor(img, grayImg, cv::COLOR_BGR2GRAY);
- // 释放对象;
- img.release();
- cv::Mat gaussImg;
- // 再高斯模糊处理(滤波);
- cv::GaussianBlur(grayImg, gaussImg, cv::Size(5, 5), 0, 0);
- // 释放对象;
- grayImg.release();
- cv::Mat blurImg;
- // 自适应阀值;
- cv::medianBlur(gaussImg, blurImg, 3);
- // 释放对象;
- gaussImg.release();
- // 局部二值化;//blocksize一般取3、5、7
- cv::adaptiveThreshold(blurImg, thresholdImg, nMaxThresholdVal, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 3, 4.5);
- // 释放对象;
- blurImg.release();
- // 判断图片是否空;
- if (thresholdImg.empty())
- return false;
- return true;
- }
- CV_API bool GaussianBlur(cv::Mat& img, cv::Size cvSize, cv::Mat& gaussImg)
- {
- if (img.empty())
- return false;
- // 再高斯模糊处理(滤波);
- cv::GaussianBlur(img, gaussImg, cvSize, 0, 0);
- // 判断图片是否空;
- if (gaussImg.empty())
- return false;
- return true;
- }
- CV_API bool GaussianBlur(std::string strImgPath, cv::Size cvSize, cv::Mat& gaussImg)
- {
- cv::Mat img;
- // 读取图片;
- if (!ReadImage(strImgPath, img))
- return false;
- // 再高斯模糊处理(滤波);
- cv::GaussianBlur(img, gaussImg, cvSize, 0, 0);
- // 判断图片是否空;
- if (gaussImg.empty())
- return false;
- return true;
- }
- CV_API bool Color2Gray(cv::Mat& img, cv::Mat& grayImg)
- {
- if (img.empty())
- return false;
- // 再高斯模糊处理(滤波);
- cv::cvtColor(img, grayImg, cv::COLOR_BGR2GRAY);
- // 判断图片是否空;
- if (grayImg.empty())
- return false;
- return true;
- }
- CV_API bool Color2Gray(std::string strImgPath, cv::Mat& grayImg)
- {
- cv::Mat img;
- // 读取图片;
- if (!ReadImage(strImgPath, img))
- return false;
- // 再高斯模糊处理(滤波);
- cv::cvtColor(img, grayImg, cv::COLOR_BGR2GRAY);
- // 判断图片是否空;
- if (grayImg.empty())
- return false;
- return true;
- }
- CV_API bool Gray2Color(cv::Mat& img, cv::Mat& colorImg)
- {
- if (img.empty())
- return false;
- // 再高斯模糊处理(滤波);
- cv::cvtColor(img, colorImg, cv::COLOR_GRAY2BGR);
- // 判断图片是否空;
- if (colorImg.empty())
- return false;
- return true;
- }
- CV_API bool ErodeImg(cv::Mat& img, cv::MorphShapes kernelShape, cv::Size kernelSize, cv::Mat& erodeImg)
- {
- if (img.empty())
- return false;
- // 获取自定义核(核形状:矩形MORPH_RECT、十字架CROSS、椭圆ELLIPSE )
- cv::Mat element = cv::getStructuringElement(kernelShape, kernelSize);
- // 再高斯模糊处理(滤波);
- cv::erode(img, erodeImg, element);
- // 判断图片是否空;
- if (erodeImg.empty())
- return false;
- return true;
- }
- CV_API bool DilateImg(cv::Mat& img, cv::MorphShapes kernelShape, cv::Size kernelSize, cv::Mat& dilateImg)
- {
- if (img.empty())
- return false;
- // 获取自定义核(核形状:矩形MORPH_RECT、十字架CROSS、椭圆ELLIPSE )
- cv::Mat element = cv::getStructuringElement(kernelShape, kernelSize);
- // 再高斯模糊处理(滤波);
- cv::dilate(img, dilateImg, element);
- // 判断图片是否空;
- if (dilateImg.empty())
- return false;
- return true;
- }
- CV_API bool CutPictures(cv::Mat& img, cv::Rect cvRect, cv::Mat& roiImg)
- {
- if (img.empty())
- return false;
- if (cvRect.empty())
- return false;
- // 裁剪ROI区域;
- roiImg = img(cvRect);
- // 判断图片是否空;
- if (roiImg.empty())
- return false;
- return true;
- }
- CV_API bool CutPictures(std::string strImgPath, cv::Rect cvRect, cv::Mat& roiImg)
- {
- cv::Mat img;
- // 读取图片;
- if (!ReadImage(strImgPath, img))
- return false;
- if (cvRect.empty())
- return false;
- // 裁剪ROI区域;
- roiImg = img(cvRect);
- // 释放原图;
- img.release();
- // 判断图片是否空;
- if (roiImg.empty())
- return false;
- return true;
- }
- CV_API bool CutPictures(std::string strImgPath, cv::Rect cvRect, std::string strRoiImgPath)
- {
- cv::Mat img;
- // 读取图片;
- if (!ReadImage(strImgPath, img))
- return false;
- if (cvRect.empty())
- return false;
- cv::Mat roiImg;
- // 裁剪ROI区域;
- roiImg = img(cvRect);
- // 释放原图;
- img.release();
- // 判断图片是否空;
- if (roiImg.empty())
- return false;
- cv::imwrite(strRoiImgPath.c_str(), roiImg);
- roiImg.release();
- return true;
- }
- CV_API bool DrawContours(cv::Mat& binImg, cv::Mat& drawImg, bool InternalContour, bool bPerimeter, long nMinPerimeter, long nMaxPerimeter, bool bArea, long nMinArea, long nMaxArea)
- {
- // 图片空或都不是单通道;
- if (binImg.empty() || binImg.channels() > 1)
- return false;
- if (drawImg.empty()) {
- // 复制到目标中;
- binImg.copyTo(drawImg);
- // 再转为BGR;
- cv::cvtColor(drawImg, drawImg, cv::COLOR_GRAY2BGR);
- }
- // 轮廓;
- vector<vector<cv::Point>> contours;
- // 轮廓关系;
- vector<cv::Vec4i> hierarchy;
- // 获取轮廓区域;
- if (InternalContour)
- {
- // 所有轮廓,内外轮廓分等级;
- findContours(binImg, contours, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);
- // 所有轮廓,内外轮廓不分等级,独立;
- //findContours(m_ImgThreshold, m_contours, m_hierarchy, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);
- }
- else
- {
- // RETR_EXTERNAL=只检索最外面的轮廓;
- findContours(binImg, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
- }
- vector<vector<cv::Point>>::iterator it = contours.begin();
- for (int i = 0; it != contours.end(); it++, i++)
- {
- if (bPerimeter && !bArea)
- {
- if (arcLength(*it, true) < nMinPerimeter || arcLength(*it, true) > nMaxPerimeter)
- continue;
- }
- else if (!bPerimeter && bArea)
- {
- if (contourArea(*it) < nMinArea || contourArea(*it) > nMaxArea)
- continue;
- }
- else if (bArea && bPerimeter)
- {
- if ((arcLength(*it, true) < nMinPerimeter || arcLength(*it, true) > nMaxPerimeter) || (contourArea(*it) < nMinArea || contourArea(*it) > nMaxArea))
- continue;
- }
- // 随机色填充轮廓;
- cv::Scalar color = cv::Scalar(rand() % 255, rand() % 255, rand() % 255);
- // 输出轮廓图;
- cv::drawContours(drawImg, contours, i, color, cv::FILLED, 8, hierarchy);
- }
- if (drawImg.empty())
- return false;
- return true;
- }
- CV_API bool MatchSingleImage(cv::Mat& img, cv::Mat templImg, double& matchVal, cv::Rect& matchRect)
- {
- if (img.empty() || templImg.empty())
- return false;
- /*
- 模板匹配的匹配方式:
- 0:CV_TM_SQDIFF 平方差匹配法:最好匹配为0。 匹配越差,匹配值越大。
- 这类方法利用图像与模板各个像素差值的平方和来进行匹配,最好匹配为 0。 匹配越差,匹配值越大。
- 1:CV_TM_SQDIFF_NORMED 归一化平方差匹配法:最好匹配为0。 匹配越差,匹配值越大。
- 这个方法其实和差值平方和算法是类似的。只不过对图像和模板进行了标准化操作
- 2:CV_TM_CCORR 相关匹配法:0最差匹配,越接近1越完美;
- 这类方法采用模板和图像的互相关计算作为相似度的度量方法,所以较大的数表示匹配程度较高,0标识最坏的匹配效果。
- 3:CV_TM_CCORR_NORMED 归一化相关匹配法:0最差匹配,越接近1越完美;
- 这个方法和 标准化差值平方和匹配 类似,都是去除了亮度线性变化对相似度计算的影响。可以保证图像和模板同时变亮或变暗k倍时结果不变。
- 4:CV_TM_CCOEFF 相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。
- 这种方法也叫做相关匹配,但是和上面的 CV_TM_CCORR 匹配方法还是有不通过的。简单的说,这里是把图像和模板都减去了各自的平均值,使得这两幅图像都没有直流分量
- 5:CV_TM_CCOEFF_NORMED 归一化相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。
- 这是 OpenCV 支持的最复杂的一种相似度算法。
- 这里的相关运算就是数理统计学科的相关系数计算方法。
- 具体的说,就是在减去了各自的平均值之外,还要各自除以各自的方差。
- 经过减去平均值和除以方差这么两步操作之后,无论是我们的待检图像还是模板都被标准化了,
- 这样可以保证图像和模板分别改变光照亮不影响计算结果。计算出的相关系数被限制在了 -1 到 1 之间,
- 1 表示完全相同,-1 表示两幅图像的亮度正好相反,0 表示两幅图像之间没有线性关系。
- */
- cv::Mat resultImg;
- cv::matchTemplate(img, templImg, resultImg, cv::TM_CCOEFF_NORMED);
- if (resultImg.empty())
- return false;
- // 最小和最大匹配值;
- double lv_nMinVal = 0.0;
- double lv_nMaxVal = 0.0;
- // 匹配的坐标点;
- cv::Point lv_nMinLoc = cv::Point(0, 0);
- cv::Point lv_nMaxLoc = cv::Point(0, 0);
- cv::minMaxLoc(resultImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
- // TM_CCOEFF_NORMED匹配是取最大值为匹配值;
- matchVal = lv_nMaxVal;
- // 匹配区域,使用最大区域;
- matchRect.x = lv_nMaxLoc.x;
- matchRect.y = lv_nMaxLoc.y;
- matchRect.width = templImg.cols;
- matchRect.height = templImg.rows;
- #ifdef _DEBUG
- // 在原图上框出模板位置;
- cv::Mat showImg;
- img.copyTo(showImg);
- cv::rectangle(showImg,
- cv::Point(lv_nMaxLoc.x, lv_nMaxLoc.y),
- cv::Point(lv_nMaxLoc.x + templImg.cols, lv_nMaxLoc.y + templImg.rows),
- cv::Scalar(rand() % 255, rand() % 255, rand() % 255),
- 2,
- cv::LINE_AA,
- 0);
- // 输出到文件中;
- imwrite("showImg.png", showImg);
- // 释放对象;
- showImg.release();
- #endif
- // 释放对象;
- resultImg.release();
- return true;
- }
- CV_API bool MatchSingleImage(cv::Mat& img, std::string strTmpImg, double& matchVal, cv::Rect& matchRect)
- {
- if (img.empty())
- return false;
- // 读取模板图片;
- cv::Mat templImg = imread(strTmpImg.c_str(), cv::IMREAD_COLOR);
- if (templImg.empty()) {
- return false;
- }
- cv::Mat resultImg;
- cv::matchTemplate(img, templImg, resultImg, cv::TM_CCOEFF_NORMED);
- if (resultImg.empty()) {
- templImg.release();
- return false;
- }
- // 最小和最大匹配值;
- double lv_nMinVal = 0.0;
- double lv_nMaxVal = 0.0;
- // 匹配的坐标点;
- cv::Point lv_nMinLoc = cv::Point(0, 0);
- cv::Point lv_nMaxLoc = cv::Point(0, 0);
- cv::minMaxLoc(resultImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
-
- // TM_CCOEFF_NORMED匹配是取最大值为匹配值;
- matchVal = lv_nMaxVal;
- // 匹配区域,使用最大区域;
- matchRect.x = lv_nMaxLoc.x;
- matchRect.y = lv_nMaxLoc.y;
- matchRect.width = templImg.cols;
- matchRect.height = templImg.rows;
- #ifdef _DEBUG
- // 在原图上框出模板位置;
- cv::Mat showImg;
- img.copyTo(showImg);
- cv::rectangle(showImg,
- cv::Point(lv_nMaxLoc.x, lv_nMaxLoc.y),
- cv::Point(lv_nMaxLoc.x + templImg.cols, lv_nMaxLoc.y + templImg.rows),
- cv::Scalar(rand() % 255, rand() % 255, rand() % 255),
- 2,
- cv::LINE_AA,
- 0);
- // 输出到文件中;
- imwrite("showImg.png", showImg);
- // 释放对象;
- showImg.release();
- #endif
- // 释放对象;
- templImg.release();
- resultImg.release();
- return true;
- }
- CV_API bool MatchSingleImage(std::string strImg, std::string strTmpImg, double& matchVal, cv::Rect& matchRect)
- {
- cv::Mat img;
- cv::Mat templImg;
- if (!ReadImage(strImg.c_str(), img) )
- return false;
- if (!ReadImage(strTmpImg.c_str(), templImg)) {
- img.release();
- return false;
- }
- cv::Mat resultImg;
- cv::matchTemplate(img, templImg, resultImg, cv::TM_CCOEFF_NORMED);
- if (resultImg.empty()) {
- img.release();
- templImg.release();
- return false;
- }
- // 最小和最大匹配值;
- double lv_nMinVal = 0.0;
- double lv_nMaxVal = 0.0;
- // 匹配的坐标点;
- cv::Point lv_nMinLoc = cv::Point(0, 0);
- cv::Point lv_nMaxLoc = cv::Point(0, 0);
- cv::minMaxLoc(resultImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
- // TM_CCOEFF_NORMED匹配是取最大值为匹配值;
- matchVal = lv_nMaxVal;
- // 匹配区域,使用最大区域;
- matchRect.x = lv_nMaxLoc.x;
- matchRect.y = lv_nMaxLoc.y;
- matchRect.width = templImg.cols;
- matchRect.height = templImg.rows;
- #ifdef _DEBUG
- // 在原图上框出模板位置;
- cv::Mat showImg;
- img.copyTo(showImg);
- cv::rectangle(showImg,
- cv::Point(lv_nMaxLoc.x, lv_nMaxLoc.y),
- cv::Point(lv_nMaxLoc.x + templImg.cols, lv_nMaxLoc.y + templImg.rows),
- cv::Scalar(rand() % 255, rand() % 255, rand() % 255),
- 2,
- cv::LINE_AA,
- 0);
- // 输出到文件中;
- imwrite("showImg.png", showImg);
- // 释放对象;
- showImg.release();
- #endif
- // 释放对象;
- img.release();
- templImg.release();
- resultImg.release();
- return true;
- }
- CV_API bool Mat2Bitmap(cv::Mat& img, CBitmap& bitmap)
- {
- return CV_API bool();
- }
- CV_API bool Mat2HBitmap(cv::Mat& img, HBITMAP& bitmap)
- {
- //MAT类的TYPE=(nChannels-1+ CV_8U)<<3
- int nChannels = (img.type() >> 3) - CV_8U + 1;
- int iSize = img.cols * img.rows * nChannels;
- bitmap = CreateBitmap(img.cols, img.rows, 1, nChannels * 8, img.data);
- return true;
- }
- CV_API bool Mat2GdiplusBitmap(cv::Mat& img, Gdiplus::Bitmap& bitmap)
- {
- return CV_API bool();
- }
- CV_API bool Bitmap2Mat(CBitmap& bitmap, cv::Mat& img)
- {
- return CV_API bool();
- }
- CV_API bool HBitmap2Mat(HBITMAP& bitmap, cv::Mat& img)
- {
- return CV_API bool();
- }
- CV_API bool GdiplusBitmap2Mat(Gdiplus::Bitmap& bitmap, cv::Mat& img)
- {
- return CV_API bool();
- }
|