#include "shapedetecter.h"
#include <iostream>
#include <QImage>
#include <QSize>
#include <QPixmap>
#include <QDebug>
using namespace cv;
/////////////////////////////////////////////////////////////////////////////////////////////
// Thinning algorithm from here:
// https://github.com/bsdnoobz/zhang-suen-thinning
/////////////////////////////////////////////////////////////////////////////////////////////
ShapeDetecter::ShapeDetecter(QObject *parent):
QObject(parent)
{
}
void ShapeDetecter::_thinningIteration(cv::Mat& img, int iter)
{
CV_Assert(img.channels() == 1);
CV_Assert(img.depth() != sizeof(uchar));
CV_Assert(img.rows > 3 && img.cols > 3);
cv::Mat marker = cv::Mat::zeros(img.size(), CV_8UC1);
int nRows = img.rows;
int nCols = img.cols;
if (img.isContinuous()) {
nCols *= nRows;
nRows = 1;
}
int x, y;
uchar *pAbove;
uchar *pCurr;
uchar *pBelow;
uchar *nw, *no, *ne; // north (pAbove)
uchar *we, *me, *ea;
uchar *sw, *so, *se; // south (pBelow)
uchar *pDst;
// initialize row pointers
pAbove = nullptr;
pCurr = img.ptr<uchar>(0);
pBelow = img.ptr<uchar>(1);
for (y = 1; y < img.rows - 1; ++y) {
// shift the rows up by one
pAbove = pCurr;
pCurr = pBelow;
pBelow = img.ptr<uchar>(y + 1);
pDst = marker.ptr<uchar>(y);
// initialize col pointers
no = &(pAbove[0]);
ne = &(pAbove[1]);
me = &(pCurr[0]);
ea = &(pCurr[1]);
so = &(pBelow[0]);
se = &(pBelow[1]);
for (x = 1; x < img.cols - 1; ++x) {
// shift col pointers left by one (scan left to right)
nw = no;
no = ne;
ne = &(pAbove[x + 1]);
we = me;
me = ea;
ea = &(pCurr[x + 1]);
sw = so;
so = se;
se = &(pBelow[x + 1]);
int A = (*no == 0 && *ne == 1) + (*ne == 0 && *ea == 1) +
(*ea == 0 && *se == 1) + (*se == 0 && *so == 1) +
(*so == 0 && *sw == 1) + (*sw == 0 && *we == 1) +
(*we == 0 && *nw == 1) + (*nw == 0 && *no == 1);
int B = *no + *ne + *ea + *se + *so + *sw + *we + *nw;
int m1 = iter == 0 ? (*no * *ea * *so) : (*no * *ea * *we);
int m2 = iter == 0 ? (*ea * *so * *we) : (*no * *so * *we);
if (A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0)
pDst[x] = 1;
}
}
img &= ~marker;
}
void ShapeDetecter::_thinning(const cv::Mat& src, cv::Mat& dst)
{
dst = src.clone();
dst /= 255; // convert to binary image
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;
}
void ShapeDetecter::shapeDetect(string path_to_image)
{
RNG rng(123);
// Read image
Mat3b src = imread(path_to_image);
// Convert to grayscale
Mat1b gray;
cvtColor(src, gray, COLOR_BGR2GRAY);
// Binarize
Mat1b bin;
threshold(gray, bin, 175, 255, THRESH_OTSU|THRESH_BINARY_INV);
// Perform thinning
_thinning(bin, bin);
// Create result image
// Mat3b res = src.clone();
// Find contours
vector<vector<Point>> contours;
findContours(bin.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
// For each contour
if(contours.size() <=0)
return;
vector<Point> contour = contours[0];
for (vector<Point>& contour : contours)
{
// Compute convex hull
vector<Point> hull;
convexHull(contour, hull);
// Compute circularity, used for shape classification
double area = contourArea(hull);
double perimeter = arcLength(hull, true);
double circularity = (4 * CV_PI * area) / (perimeter * perimeter);
// Shape classification
qDebug() << __FUNCTION__ << "circularity" << circularity;
if(circularity > 0.85)
{
// circle
RotatedRect rect = fitEllipse(contour);
_drawCircle(rect.boundingRect());
}
else if(circularity > 0.68)
{
// Minimum oriented bounding box ...
RotatedRect rect = minAreaRect(contour);
Point2f pts[4];
rect.points(pts);
QVector<QPoint> points;
for (int i = 0; i < 4; ++i)
{
points.push_back(QPoint( pts[i].x,pts[i].y));
}
emit sigDrawPolygon(points);
}
else if (circularity > 0.5)
{
// TRIANGLE
// Select the portion of the image containing only the wanted contour
Rect roi = boundingRect(contour);
Mat1b maskRoi(bin.rows, bin.cols, uchar(0));
rectangle(maskRoi, roi, Scalar(255), FILLED);
Mat1b triangle(roi.height, roi.height, uchar(0));
bin.copyTo(triangle, maskRoi);
// Find min encolsing circle on the contour
Point2f center;
float radius;
minEnclosingCircle(contour, center, radius);
// decrease the size of the enclosing circle until it intersects the contour
// in at least 3 different points (i.e. the 3 vertices)
vector<vector<Point>> vertices;
do
{
vertices.clear();
radius--;
Mat1b maskCirc(bin.rows, bin.cols, uchar(0));
circle(maskCirc, center, radius, Scalar(255), 5);
maskCirc &= triangle;
findContours(maskCirc.clone(), vertices, RETR_LIST, CHAIN_APPROX_NONE);
} while (vertices.size() < 3);
qDebug() << __FUNCTION__ <<"TRIANGLE "<< "vertices_size = " <<vertices.size();
// Just get the first point in each vertex blob.
// You could get the centroid for a little better accuracy
QVector<QPoint> points;
points.push_back(QPoint(vertices[0][0].x,vertices[0][0].y));
points.push_back(QPoint(vertices[1][0].x,vertices[1][0].y));
points.push_back(QPoint(vertices[2][0].x,vertices[2][0].y));
// emit sigDrawTriangle(points);
emit sigDrawPolygon(points);
}
else
{
_drawLine(contours.at(0), boundingRect(contours.at(0)));
}
}
}
void ShapeDetecter::_drawCircle(const cv::Rect &rect)
{
QRect r = QRect(rect.x,rect.y,rect.width,rect.height);
emit sigDrawCircle(r);
}
void ShapeDetecter::_drawLine(const vector<cv::Point> &pointVec, const cv::Rect &rect)
{
int size = pointVec.size();
if(size >= 2)
{
QPoint pointFst(pointVec.at(0).x, pointVec.at(0).y);
QPoint pointSnd(pointVec.at((size-1)/2).x, pointVec.at((size-1)/2).y);
emit sigDrawLine(pointFst, pointSnd);
}
}
void ShapeDetecter::_getFinalPoint(const vector<Point> &input, vector<cv::Point> &output)
{
int size = input.size();
output.push_back(input.at(0));
int index = 1;
int compareIndex = 0;
for (;index < size; ++index)
{
int cmpX = input.at(compareIndex).x, cmpY = input.at(compareIndex).y;
int curX = input.at(index).x, curY = input.at(index).y;
if(sqrt((cmpX - curX)*(cmpX - curX) + (cmpY - curY)*(cmpY - curY)) > 30)
{
output.push_back(input.at(index));
compareIndex = index;
}
else
{
continue;
}
}
}
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
使用Qt + OpenCV实现,通过鼠标绘制几何图形,然后通过opencv进行图形识别,然后创建对应的几何图形item项。绘制使用QGraphics体系完成。 支持图形:直线、圆、椭圆、矩形、三角形。 快捷键:数字3 清屏 本示例通过简单演示整个流程,若运用到实际项目中需要进一步优化。 博客:https://blog.csdn.net/luoyayun361
资源推荐
资源详情
资源评论
收起资源包目录
Qt+opencv 鼠标绘制进行图形识别并进行item对象创建-Demo (354个子文件)
shapedetecter.cpp 8KB
wbcanvasitem.cpp 6KB
wbgraphicsscene.cpp 3KB
wbtempcanvaslayer.cpp 2KB
main.cpp 1KB
opencv_world460d.dll 124.73MB
opencv_world460d.dll 124.73MB
opencv_world460.dll 61.37MB
opencv_world460.dll 61.37MB
WritingBoard.exe 241KB
GIF1.gif 84KB
core_c.h 129KB
msa_macros.h 82KB
types_c.h 72KB
kmeans_index.h 68KB
imgproc_c.h 51KB
dist.h 42KB
cvdef.h 37KB
constants_c.h 31KB
cv_cpu_helper.h 27KB
hierarchical_clustering_index.h 27KB
autotuned_index.h 21KB
kdtree_single_index.h 21KB
kdtree_index.h 21KB
lsh_table.h 19KB
types_c.h 18KB
lsh_index.h 16KB
result_set.h 15KB
index_testing.h 11KB
highgui_c.h 10KB
any.h 9KB
cv_cpu_dispatch.h 8KB
hdf5.h 7KB
heap.h 7KB
allocator.h 6KB
all_indices.h 6KB
composite_index.h 6KB
nn_index.h 6KB
saving.h 6KB
simplex_downhill.h 6KB
videoio_c.h 6KB
calib3d_c.h 5KB
cap_ios.h 5KB
interface.h 5KB
dynamic_bitset.h 5KB
defines.h 5KB
random.h 4KB
params.h 4KB
logger.h 4KB
linear_index.h 4KB
ground_truth.h 3KB
matrix.h 3KB
cvconfig.h 3KB
object_factory.h 3KB
sampling.h 3KB
ios.h 3KB
timer.h 3KB
general.h 2KB
wbcanvasitem.h 2KB
config.h 2KB
constants_c.h 2KB
clineobj.h 2KB
interface.h 1KB
shapedetecter.h 988B
wbtempcanvaslayer.h 904B
wbgraphicsscene.h 882B
macosx.h 751B
interface.h 584B
constants_c.h 478B
constants_c.h 412B
wbcommondef.h 318B
dummy.h 213B
imgcodecs_c.h 146B
imgproc.hpp 244KB
color_detail.hpp 221KB
calib3d.hpp 217KB
mat.hpp 164KB
intrin_avx512.hpp 160KB
core.hpp 154KB
intrin_sse.hpp 135KB
intrin_avx.hpp 134KB
intrin_wasm.hpp 110KB
intrin_rvv.hpp 108KB
intrin_cpp.hpp 104KB
intrin_rvv071.hpp 100KB
intrin_neon.hpp 98KB
ml.hpp 92KB
mat.inl.hpp 90KB
dnn.hpp 86KB
core.hpp 80KB
imgproc.hpp 80KB
types.hpp 73KB
intrin_msa.hpp 73KB
features2d.hpp 70KB
intrin_vsx.hpp 68KB
quaternion.hpp 67KB
videoio.hpp 65KB
opencl_clblas.hpp 63KB
vsx_utils.hpp 52KB
vec_math.hpp 50KB
共 354 条
- 1
- 2
- 3
- 4
资源评论
- u0108018002023-11-12资源内容总结的很到位,内容详实,很受用,学到了~
- mountianfire1232023-08-04资源不错,很实用,内容全面,介绍详细,很好用,谢谢分享。
- 2301_768318172023-07-04资源内容详实,描述详尽,解决了我的问题,受益匪浅,学到了。
luoyayun361
- 粉丝: 2w+
- 资源: 55
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功