钉子绕线画

按照绕线画算法这篇博客给出的思路:

我也来尝试一下。

数据结构

struct Point2 {
	int x, y;
	bool operator< (const Point2 b) const
	{
		if (x == b.x)return y < b.y;
		return x < b.x;
	}
};
struct PointPair {
	Point2 p1, p2;
	PointPair(Point2 a, Point2 b)
	{
		if (a < b)p1 = a, p2 = b;
		else p1 = b, p2 = a;
	}
	bool operator< (const PointPair b)const
	{
		if (p1 < b.p1)return true;
		if (b.p1 < p1)return false;
		return p2 < b.p2;
	}
};

算法

Mat imgMask;
double meanPix(Mat& img, Point2 a, Point2 b)
{
	int len = max(abs(a.x - b.x), abs(a.y - b.y));
	double dx = (a.x - b.x) * 1.0 / len;
	double dy = (a.y - b.y) * 1.0 / len;
	double x = b.x, y = b.y;
	int s = 0;
	for (int i = 1; i < len; i++) {
		x += dx, y += dy;
		s += int(img.at<unsigned char>(int(x), int(y))* imgMask.at<unsigned char>(int(x), int(y)));
	}
	return s * 1.0 / len;
}
void subPix(Mat& img, Point2 a, Point2 b, int d)
{
	int len = max(abs(a.x - b.x), abs(a.y - b.y));
	double dx = (a.x - b.x) * 1.0 / len;
	double dy = (a.y - b.y) * 1.0 / len;
	double x = b.x, y = b.y;
	int s = 0;
	for (int i = 1; i < len; i++) {
		x += dx, y += dy;
		int pix = img.at<unsigned char>(int(x), int(y));
		img.at<unsigned char>(int(x), int(y)) = max(0, pix - d);
	}
}
void setPix(Mat& img, Point2 a, Point2 b, int d)
{
	int len = max(abs(a.x - b.x), abs(a.y - b.y));
	double dx = (a.x - b.x) * 1.0 / len;
	double dy = (a.y - b.y) * 1.0 / len;
	double x = b.x, y = b.y;
	int s = 0;
	for (int i = 1; i < len; i++) {
		x += dx, y += dy;
		img.at<unsigned char>(int(x), int(y)) = d;
	}
}

int main()
{
	const int n = 600;
	int lineNum = 800;
	Mat img = imread("D:/im.jpg", 0);
	resize(img, img, Size(n + 1, n+ 1));
	Mat src;
	img = 255 - img;
	imshow("img", img);
	imgMask = img.clone();
	blur(imgMask, imgMask, Size(19, 19));
	//imshow("img2", imgMask);
	vector<Point2>vp;
	for (int i = 0; i < 360; i++) {
		double r = i * 3.1415926 / 180;
		vp.push_back({ int(n / 2 * sin(r)) + 300, int(n / 2 * cos(r)) + 300 });
	}
	Point2 p = vp[0];
	map< Line, int>m;
	for (auto& pi : vp)m[Line(pi, pi)] = 1;
	Mat ans = img.clone();
	ans = 255;
	while (lineNum--) {
		Point2 next = p;
		double s0 = 0;
		for (auto& pi : vp) {
			if (m[Line(p, pi)])continue;
			double s = meanPix(img, p, pi);
			if (s0 < s)s0 = s, next = pi;
		}
		subPix(img, p, next, 100);
		setPix(ans, p, next, 100);
		m[Line(p, next)] = 1;
		p = next;
	}
	//imshow("img3", img);
	imshow("ans", ans);
	waitKey(0);
	return 0;
}

结果:

 原图:

远处对比:

和某bao上的效果对比,还是有很大差距的。

我想了一下,上面的算法思路虽然简单,但是有效性确实有限。

比如这种情况:

要想一笔画,每一条弦都有用,就很难。

实际上应该运行一部分弦是没用的,这样就能得到这种解:

右边的2条弦没有命中目标,但是很有必要。

所以个人感觉某bao上的AI算法,应该是类似于分割算法,分割成若干直线。

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: e写的钉子绕线生成软件是一款非常有用的数字绘工具。这个软件能够让用户在计算机上绘制出类似于实物钉子绕线艺术作品的图形,而无需使用真实的绳子和钉子。通过简单的操作和调整,用户可以创建出多种不同的线条和纹理,然后使用这些线条和纹理来形成一个完整的数字绘作品。在这个软件中,用户可以自由选择线条的颜色、粗细和样式,也可以设置纹理的类型、大小和密度等。此外,软件还提供了多个模板和预设,让用户可以快速地创建出各种不同的线条和纹理组合,并实现各种艺术效果。总之,e写的钉子绕线生成软件是一款非常实用的数字绘工具,它为用户提供了一种新的创作方式,使得他们能够更加自由和灵活地表达自己的想法和创意。无论是初学者还是专业家,都可以从这款软件中获得很多的灵感和收获。 ### 回答2: e写的钉子绕线生成软件是一款非常实用的软件,它主要用于生成各种各样的钉子绕线。这个软件具有非常好的可操作性和易用性,即使是初学者也能很快上手。在使用过程中,用户只需输入图形的基本参数,如线条颜色、宽度、粗细等,就可以生成一张漂亮的钉子绕线。同时,该软件还拥有丰富的素材库,用户可以在里面选择各种各样的图案、形状、字母等作为钉子绕线的底图,也可以自己导入自己喜欢的图片作为底图,方便快捷。 除此之外,这个软件还支持多种输出格式,用户可以将生成钉子绕线导出为各种图片格式,如jpg、png、gif等,并可以选择不同的分辨率和质,满足不同的需求。此外,该软件还支持一键分享功能,方便用户将生成钉子绕线分享给朋友或发布到社交媒体。 总的来说,e写的钉子绕线生成软件是一款非常实用的工具,不仅适用于个人创作、DIY、礼品定制等领域,也可以广泛应用于设计、广告、包装等行业,是我们创作和生活中必备的好帮手。 ### 回答3: e写的钉子绕线生成软件是一款可以帮助用户自动生成绕线的软件。绕线是将线圈绕在钉子上,通过钉子的数量、排列方式、线圈数目、线的粗细等不同因素的组合,形成不同的图形。在传统的制作过程中,需要手动布置钉子绕线,非常费时费力。而e写的钉子绕线生成软件,则为此提供了一种便捷的解决方案。 在使用该软件时,用户可以通过选择不同的参数来调整钉子的形状和排列方式,同时可以设置线的粗细和颜色,使生成绕线具有多样化的风格。此外,该软件还支持导出生成绕线为矢量图形,方便用户进行后续的编辑和制作。 该软件的使用范围非常广泛,可以被应用于艺术创作、手工制作、建筑设计等领域,为用户带来更加创新、高效的制作体验。总之,e写的钉子绕线生成软件是一款非常有实用价值的软件,具有广泛的应用前景和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值