2016-02-18 1 views
-1

в нижнем изображении у меня есть поверхность, которая не является гладкой (я не знаю ее терминологии). Я сделал бы прямую линию над белым объектом, но она имела шероховатую поверхность. Видно, весь объект не горизонтальный, и он наклонен и его угол может быть предопределен и изменен по картинке.определить прямую линию с черновой линией?

Мне нужна прямая линия, представляющая эту шероховатую поверхность (в красной коробке), которая является средней (или может быть чем-то еще, чем средняя). Наконец, мне нужна кривая y = mx + b. не могли бы вы дать свою идею или помочь мне, как мне подойти к решению.

enter image description here

enter image description here

+2

Какая операционная система? Какие инструменты? У вас есть числовые данные, которые создают изображение? У вас есть другие образцы изображений? –

+0

, так что вы ищете «линию наилучшего соответствия» (http://stackoverflow.com/questions/34554609/plotting-a-line-in-a-chart-given-the-y-intercept-and- наклон/34558330? s = 1 | 0,6304 # 34558330)? – TaW

+0

Всегда ли он повернут? Всегда ли это верхний край? Изменяется ли размер или положение белой формы? Это иногда частично из кадра? Есть ли иногда несколько объектов? –

ответ

1

Вот грубый набросок ответа, с помощью ImageMagick, который устанавливается на большинстве дистрибутивов Linux и доступна для OSX и Windows.

Сначала очистите изображение путем окрашивания черным по всему краю на 2,5% со стороны, а затем с порогом на черный и черный. Также перейдите в формат PNG, чтобы избежать потерь и ошибок. Обычно я просто обрезал изображение, обрезая некоторые края, чтобы избавиться от вашего неровного верхнего края, но это исказило бы координату y вашего ответа, поэтому я просто перекрашу его черным.

Затем нарезать вертикальными полосами шириной 1 пиксель. Это производит 394 файлов, называемых vbar-0000.png через bar-0393.png

Как и в стороне, то они выглядят так:

enter image description here

Затем перебирать вертикальные черточки ищут первый белый пиксель, чтобы получить у-координату, а мы уже знаем координату 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.

я пометил на красной позиции идентифицированных точек:

enter image description here

Когда я преобразовать вертикальную полосу в текст, в приведенном выше, я использую это:

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) 
... 
... 

МаленькийСценарийпросто ищет первое вхождение #FFFFFF, то есть белый, а затем печатает y-координату, которая сразу после первой запятой на этой строке.

Я не большой встряски на GNUplot, но я сделал командный файл с именем plot.cmd так:

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 

и получил этот

enter image description here

и он говорит мне, что уравнение

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%) 

Обратите внимание, что вы могли бы изменить последние несколько строк сценария Баша, чтобы сделать все заговоры и прочее автомагический в конце:

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

gnuplot plot.cmd 
+0

Я никогда не думал, что увижу, что кто-то делает какую-то полезную обработку изображений, используя сценарии оболочки и инструменты командной строки. Это сделало мой день :) –

+1

Это просто демонстрирует огромную силу ImageMagick в сочетании с философией Unix, объединяющей несколько мощных инструментов для выполнения большей работы. Возможно, я мог бы сделать это как однострочный, если бы не объяснял себя до конца и делал небольшие, легко удобоваримые куски! Спасибо за ваш комментарий. –

+0

Большое спасибо за ваш отличный ответ и идею. для этого изображения он работал идеально. я должен сказать, что я использую Matlab для этой задачи. У меня также есть другая картина, которую другой объект появляется поверх белого белого объекта. не могли бы вы дать мне идеал, как найти их плоские поверхности. Я демонстрирую красные линии. – Mason

1

Это основано на моем другом ответе, но я помещаю его в другой, отдельный ответ, потому что он использует совершенно разные технологии. Здесь я использую OpenCV Computer Vision Library, а не 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; 
      } 

     } 
    } 
}