Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Object 用粗线定义直线?_Object_Image Processing_Line_Signal Processing - Fatal编程技术网

Object 用粗线定义直线?

Object 用粗线定义直线?,object,image-processing,line,signal-processing,Object,Image Processing,Line,Signal Processing,在下面的图片中,我有一个不光滑的表面(我不知道它的术语)。我会在白色物体的上方画一条直线,但它有粗糙的表面。可见,整个物体不是水平的,它是倾斜的,它的角度可以预先定义,并随图片而变化 我需要一条代表粗糙表面的直线(在红色框中),这是一个平均值(或者可能不是平均值) 最后,我需要一条曲线y=mx+b。你能告诉我你的想法吗?或者帮助我如何解决这个问题 下面是一个答案的大致轮廓,使用ImageMagick,它安装在大多数Linux发行版上,可用于OSX和Windows 首先清理图像,从侧面开始,在边

在下面的图片中,我有一个不光滑的表面(我不知道它的术语)。我会在白色物体的上方画一条直线,但它有粗糙的表面。可见,整个物体不是水平的,它是倾斜的,它的角度可以预先定义,并随图片而变化

我需要一条代表粗糙表面的直线(在红色框中),这是一个平均值(或者可能不是平均值) 最后,我需要一条曲线y=mx+b。你能告诉我你的想法吗?或者帮助我如何解决这个问题


下面是一个答案的大致轮廓,使用ImageMagick,它安装在大多数Linux发行版上,可用于OSX和Windows

首先清理图像,从侧面开始,在边缘周围涂上2.5%的黑色,然后阈值化为纯黑色和白色。也可以使用PNG格式,以避免丢失和错误。我通常只是修剪图像,从边缘剪下一些来去除你的锯齿状的上边缘,但这会使你答案的y坐标倾斜,所以我只是用黑色过度渲染

然后切成1像素宽的垂直条。这将通过
bar-0393.png
产生394个名为
vbar-0000.png
的文件

另一方面,它们看起来是这样的:

convert vbar-0145.png -depth 8 txt:

# ImageMagick pixel enumeration: 1,295,255,gray
0,0: (0,0,0)  #000000  gray(0)
0,1: (0,0,0)  #000000  gray(0)
0,2: (0,0,0)  #000000  gray(0)
0,3: (0,0,0)  #000000  gray(0)
0,4: (0,0,0)  #000000  gray(0)
0,5: (0,0,0)  #000000  gray(0)
0,6: (0,0,0)  #000000  gray(0)
0,7: (0,0,0)  #000000  gray(0)
0,8: (0,0,0)  #000000  gray(0)
0,9: (0,0,0)  #000000  gray(0)
0,10: (0,0,0)  #000000  gray(0)
0,11: (0,0,0)  #000000  gray(0)
0,12: (0,0,0)  #000000  gray(0)
...
...
0,101: (0,0,0)  #000000  gray(0)
0,102: (0,0,0)  #000000  gray(0)
0,103: (0,0,0)  #000000  gray(0)
0,104: (0,0,0)  #000000  gray(0)
0,105: (65535,65535,65535)  #FFFFFF  gray(255)  <--- Here is the first white pixel starting from the top
0,106: (65535,65535,65535)  #FFFFFF  gray(255)
0,107: (65535,65535,65535)  #FFFFFF  gray(255)
0,108: (65535,65535,65535)  #FFFFFF  gray(255)
0,109: (65535,65535,65535)  #FFFFFF  gray(255)
...
...
set title 'Plotted with Gnuplot'
set ylabel 'y-axis'
set xlabel 'x-axis'
f(x)=a*x+b
fit f(x) 'points.txt' using 1:2 via a,b
plot 'points.txt',f(x) with lines linestyle 3
set terminal png large
set output 'graph.png'
set size 1,0.5
replot

然后遍历垂直条,寻找第一个白色像素以获得y坐标,因为我们已经从正在处理的垂直条的数量中知道了x坐标。抑制任何没有白色像素的线的输出,否则会使曲线拟合倾斜。为此,我将文件转换为文本-请参见末尾的注释

#!/bin/bash

# Pre-processing cleanup
# Blacken in 2.5% around all edges and threshold image to pure black and white, and move to PNG to avoid losses
convert thing.jpg -background black -gravity center -crop 95x95% -extent 374x295 -colorspace gray -threshold 50% +repage thing.png

# Get height
h=$(identify -format "%h" thing.png)

# Slice into 1-pixel wide vertical bars
convert thing.png -crop 1x vbar-%04d.png

# Iterate through all bars finding the first white pixel in each
x=1
for f in vbar*png; do
   y=$(convert "$f" -depth 8 txt: | awk -F'[,:]' '/#FFFFFF/{print $2;exit}')
   # Don't output points for vbars with no white in them - they will skew the curve fitting
   if [ ! -z $y ]; then
      # Measure from bottom left instead of top-left
      ((y=h-y))
      echo $x $y
   fi
   ((x++))
done
产生此输出的:

51 207
52 208
53 209
54 209
55 209
56 209
57 209
58 209
59 209
60 209
61 209
62 209
63 210
64 212
65 212
66 212
67 212
68 212
69 210
70 210
71 210
72 209
73 209
74 209
75 209
76 209
77 207
78 207
79 207
80 206
81 206
82 206
83 205
84 205
85 203
86 203
87 203
88 202
89 202
90 202
91 202
92 200
93 200
94 200
95 200
96 199
97 199
98 199
99 197
100 197
101 197
102 197
103 196
104 196
105 196
106 196
107 196
108 194
109 194
110 194
111 193
112 192
113 192
114 193
115 192
116 192
117 192
118 192
119 192
120 192
121 190
122 189
123 189
124 189
125 187
126 187
127 186
128 184
129 184
130 183
131 183
132 184
133 184
134 186
135 186
136 186
137 186
138 187
139 187
140 187
141 189
142 189
143 189
144 189
145 190
146 190
147 190
148 190
149 190
150 190
151 190
152 190
153 190
154 189
155 189
156 187
157 185
158 184
159 184
160 184
161 183
162 183
163 180
164 180
165 180
166 180
167 179
168 179
169 176
170 174
171 174
172 174
173 174
174 174
175 174
176 177
177 177
178 177
179 179
180 180
181 180
182 180
183 180
184 181
185 181
186 181
187 181
188 181
189 180
190 180
191 180
192 180
193 179
194 179
195 179
196 176
197 171
198 171
199 173
200 173
201 173
202 173
203 173
204 173
205 173
206 173
207 173
208 173
209 173
210 173
211 173
212 173
213 173
214 173
215 171
216 170
217 170
218 170
219 167
220 167
221 163
222 164
223 164
224 164
225 166
226 167
227 167
228 167
229 167
230 167
231 169
232 169
233 169
234 169
235 169
236 167
237 167
238 167
239 167
240 167
241 167
242 166
243 166
244 164
245 163
246 163
247 163
248 161
249 163
250 163
251 163
252 163
253 163
254 163
255 163
256 163
257 163
258 163
259 163
260 163
261 163
262 163
263 163
264 163
265 163
266 163
267 161
268 161
269 161
270 161
271 161
272 161
273 158
274 158
275 158
276 158
277 157
278 157
279 157
280 156
281 156
282 156
283 156
284 154
285 154
286 153
287 151
288 151
289 150
290 148
291 148
292 148
293 145
294 144
295 144
296 144
297 140
298 140
299 141
300 140
301 140
302 143
303 143
304 141
305 141
306 144
307 135
308 134
309 134
310 133
311 133
312 134
313 134
314 134
315 121
316 122
你可以把它输入到
GNUplot
中,得到
y=mx+c
的系数

我用红色标记了已识别点的位置:

当我将垂直条转换为文本时,在上面,我使用以下方法:

convert bar-????.png -depth 8 txt:
结果是这样的:

convert vbar-0145.png -depth 8 txt:

# ImageMagick pixel enumeration: 1,295,255,gray
0,0: (0,0,0)  #000000  gray(0)
0,1: (0,0,0)  #000000  gray(0)
0,2: (0,0,0)  #000000  gray(0)
0,3: (0,0,0)  #000000  gray(0)
0,4: (0,0,0)  #000000  gray(0)
0,5: (0,0,0)  #000000  gray(0)
0,6: (0,0,0)  #000000  gray(0)
0,7: (0,0,0)  #000000  gray(0)
0,8: (0,0,0)  #000000  gray(0)
0,9: (0,0,0)  #000000  gray(0)
0,10: (0,0,0)  #000000  gray(0)
0,11: (0,0,0)  #000000  gray(0)
0,12: (0,0,0)  #000000  gray(0)
...
...
0,101: (0,0,0)  #000000  gray(0)
0,102: (0,0,0)  #000000  gray(0)
0,103: (0,0,0)  #000000  gray(0)
0,104: (0,0,0)  #000000  gray(0)
0,105: (65535,65535,65535)  #FFFFFF  gray(255)  <--- Here is the first white pixel starting from the top
0,106: (65535,65535,65535)  #FFFFFF  gray(255)
0,107: (65535,65535,65535)  #FFFFFF  gray(255)
0,108: (65535,65535,65535)  #FFFFFF  gray(255)
0,109: (65535,65535,65535)  #FFFFFF  gray(255)
...
...
set title 'Plotted with Gnuplot'
set ylabel 'y-axis'
set xlabel 'x-axis'
f(x)=a*x+b
fit f(x) 'points.txt' using 1:2 via a,b
plot 'points.txt',f(x) with lines linestyle 3
set terminal png large
set output 'graph.png'
set size 1,0.5
replot
然后跑:

gnuplot plot.cmd
还有这个

它告诉我方程是

y = -0.26x + 225.2
GNUplot输出

After 5 iterations the fit converged.
final sum of squares of residuals : 5200.82
rel. change during last iteration : -1.49004e-07

degrees of freedom    (FIT_NDF)                        : 264
rms of residuals      (FIT_STDFIT) = sqrt(WSSR/ndf)    : 4.43848
variance of residuals (reduced chisquare) = WSSR/ndf   : 19.7001

Final set of parameters            Asymptotic Standard Error
=======================            ==========================
a               = -0.260914        +/- 0.003544     (1.358%)
b               = 225.212          +/- 0.705        (0.313%)
请注意,您可以更改bash脚本的最后几行,以便在最后自动完成所有打印和填充操作:

...
...
   fi
   ((x++))
done > points.txt

gnuplot plot.cmd

这是基于我的另一个答案,但我把它作为另一个单独的答案,因为它使用完全不同的技术。在这里,我使用OpenCV计算机视觉库而不是ImageMagick来获取另一个答案上我用红色标记的点。然后这些将被输入到GNUPlot中,就像另一个答案一样,因为我自己不想解方程:-)

我在OpenCV方面不是很有能力,可能有更快的方法来实现同样的目标

// Get x,y coordinates of first white pixel in each column of image starting from top
// Mark Setchell

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main()
{

    Mat img = imread("/Users/Mark/tmp/thing.png",IMREAD_GRAYSCALE);
    const uchar white = 255;
    int w =img.cols;
    int h =img.rows;
    for (int x = 0; x < w; ++x)
    {
       for(int y = 0; y < h; ++y)
       {
          unsigned char val=img.at<uchar>(y, x);
          if (val == white) {
              int inverted = h - y;
              cout << x << " " << inverted << endl;
              break;
          }

       }
    }
}
//从顶部开始获取图像每列中第一个白色像素的x,y坐标
//马克·塞切尔
#包括
#包括
使用名称空间cv;
使用名称空间std;
int main()
{
Mat img=imread(“/Users/Mark/tmp/thing.png”,imread\u GRAYSCALE);
常数uchar-white=255;
int w=img.cols;
int h=img.rows;
对于(int x=0;x什么操作系统?什么工具?你有创建图像的数字数据吗?你有其他样本图像吗?所以你在寻找?它是否旋转过?它是否总是顶部边缘?白色形状是否改变大小或位置?它有时部分脱离框架?有时有多个对象吗?我从没想过我会看到一些对象我不会使用shell脚本和命令行工具进行任何有用的图像处理。这让我很高兴:)它展示了ImageMagick的巨大威力,并结合了Unix的理念,将几个强大的工具结合起来,完成更大的工作。如果我不是一路解释和制作sma的话,我可能可以作为一行程序来完成L,容易消化的块!谢谢你的评论。非常感谢你伟大的回答和想法。对于这张图片,它工作得非常完美。我不得不说我使用matlab完成这项任务。我还有一些其他图片,其中另一个对象出现在当前的白色对象上。你能告诉我如何找到它们的平面吗用红线表示抗议。很高兴这对你有用!我想你会在你的问题中添加另一张图片。如果是这样,请添加一张未标记的图片和一张红色标记的图片,这样我就可以得到一张干净的未标记图片来玩。stackoverflow不允许我上载3张图片。我只能上载2张图片。我需要一个平面来放置下面的白色对象(你发现它很完美)和底部的一行。在链接中,我显示了我需要什么行。