小伙伴们大家好,今天给大家分享一个使用QT和opencv实现的一个找不同的小demo,此demo可以用于大家来找茬小游戏,提高你查询图片不同的速度
使用QT和opencv
第一步:绘制两个透明视窗,用于采集视窗内的图片,视口大小可以修改,位置可以调整
第二部:采集视窗内的图像,并且使用opencv比较对应的图像不同之处
第三步:在视口绘制出对应的不同位置
绘制透明区域:
void DifferentWidget::paintEvent(QPaintEvent *event)
{
QPainter p(this );
p.setCompositionMode( QPainter::CompositionMode_Clear );
p.fillRect( rect1_, Qt::SolidPattern );
p.fillRect( rect2_, Qt::SolidPattern );
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
QPen pen;
pen.setWidth(1);
pen.setColor(Qt::red);
painter.setPen(pen);
// 绘制比较之后的框
for(const auto &rect : rects_)
{
QRect rect1;
rect1.setX(rect.x+rect1_.x());
rect1.setY(rect.y+rect1_.y());
rect1.setHeight(rect.height);
rect1.setWidth(rect.width);
painter.drawRect(rect1);
rect1.setX(rect.x+rect2_.x());
rect1.setY(rect.y+rect2_.y());
rect1.setHeight(rect.height);
rect1.setWidth(rect.width);
painter.drawRect(rect1);
}
}
比较图片不同之处:
std::vector<cv::Rect> DifferentWidget::imageSubtract(const cv::Mat& image1, const cv::Mat& image2)
{
if (image1.empty() || image2.empty())
{
return {};
}
cv::Mat cv_src1 = image1.clone();
cv::Mat cv_src2 = image2.clone();
if ((image1.rows != image2.rows) || (image1.cols != image2.cols))
{
int rows = (image1.rows + image2.rows) / 2;
int cols = (image1.cols + image2.cols) / 2;
cv::resize(image1, cv_src1, cv::Size(cols, rows));
cv::resize(image2, cv_src2, cv::Size(cols, rows));
}
cv::Mat image1_gary, image2_gary;
if (cv_src1.channels() != 1)
{
cvtColor(cv_src1, image1_gary, cv::COLOR_BGR2GRAY);
}
if (cv_src2.channels() != 1)
{
cvtColor(cv_src2, image2_gary, cv::COLOR_BGR2GRAY);
}
cv::Mat frameDifference, absFrameDifferece;
cv::Mat previousGrayFrame = image2_gary.clone();
//图1减图2
subtract(image1_gary, image2_gary, frameDifference, cv::Mat(), CV_16SC1);
//取绝对值
absFrameDifferece = abs(frameDifference);
//位深的改变
absFrameDifferece.convertTo(absFrameDifferece, CV_8UC1, 1, 0);
cv::Mat segmentation;
//阈值处理(这一步很关键,要调好二值化的值)
threshold(absFrameDifferece, segmentation, 10, 255, cv::THRESH_BINARY);
//threshold(absFrameDifferece, segmentation, 0, 255, cv::THRESH_OTSU);
//形态学处理(开闭运算)
//形态学处理用到的算子
cv::Mat morphologyKernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5), cv::Point(-1, -1));
morphologyEx(segmentation, segmentation, cv::MORPH_CLOSE, morphologyKernel, cv::Point(-1, -1), 2, cv::BORDER_REPLICATE);
//找边界
std::vector< std::vector<cv::Point> > contours;
std::vector<cv::Vec4i> hierarchy;
findContours(segmentation, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point(0, 0));//CV_RETR_TREE
std::vector< std::vector<cv::Point> > contours_poly(contours.size());
std::vector<cv::Rect> boundRect;
for (int index = 0; index < contours.size(); index++)
{
approxPolyDP(cv::Mat(contours[index]), contours_poly[index], 3, true);
cv::Rect rect = cv::boundingRect(cv::Mat(contours_poly[index]));
boundRect.push_back(rect);
}
return boundRect;
}
透明窗口和转换的问题
项目开源地址:https://gitee.com/turbolove/find-difference.git