首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >水稻粒数

水稻粒数
EN

Code Golf用户
提问于 2014-11-02 02:42:46
回答 5查看 22.7K关注 0票数 86

考虑这10张不同数量的白米未煮谷物的图片。

这些只是缩略图。单击图像以查看完整大小的图像。

答:

B:

C:

D:

E:

F:

G:

H:

我:

J:

谷物计数:A: 3, B: 5, C: 12, D: 25, E: 50, F: 83, G: 120, H:150, I: 151, J: 200

注意到..。

  • 谷物可能相互接触,但它们从不重叠。粮食的布局从来不超过一粒高。
  • 这些图像有不同的尺寸,但由于相机和背景是静止的,所以它们的尺度是一致的。
  • 这些颗粒永远不会超出边界,也不会触及图像边界。
  • 背景总是相同的相同的黄白色的颜色。
  • 小的和大的都是一粒一粒的。

这5点是所有这类图像的保证。

挑战

编写一个程序,接收这样的图像,并尽可能准确地计算稻谷的数量。

您的程序应该获取图像的文件名,并打印它计算出来的颗粒数。您的程序必须至少为这些图像文件格式中的一种工作: JPEG、Bitmap、PNG、GIF、TIFF (现在这些图像都是JPEG格式)。

您可以使用图像处理和计算机视觉库。

您可能不会硬编码10个示例图像的输出。你的算法应该适用于所有类似的稻谷图像。如果图像面积小于2000*2000像素,并且有不到300粒大米,它应该能够在像样的现代计算机上运行不到5分钟。

评分

对于这10幅图像中的每一幅,都取实际颗粒数减去程序预测的颗粒数的绝对值。把这些绝对值加起来,得到你的分数。得分最低者获胜。0的分数是完美的。

如果结果是平局,最高投票的答案将获胜。我可以在额外的图像上测试你的程序,以验证它的有效性和准确性。

EN

回答 5

Code Golf用户

回答已采纳

发布于 2014-11-03 16:54:02

Mathematica,得分: 7

代码语言:javascript
复制
i = {"http://i.stack.imgur.com/8T6W2.jpg",  "http://i.stack.imgur.com/pgWt1.jpg", 
     "http://i.stack.imgur.com/M0K5w.jpg",  "http://i.stack.imgur.com/eUFNo.jpg", 
     "http://i.stack.imgur.com/2TFdi.jpg",  "http://i.stack.imgur.com/wX48v.jpg", 
     "http://i.stack.imgur.com/eXCGt.jpg",  "http://i.stack.imgur.com/9na4J.jpg",
     "http://i.stack.imgur.com/UMP9V.jpg",  "http://i.stack.imgur.com/nP3Hr.jpg"};

im = Import /@ i;

我认为这些函数的名称有足够的描述性:

代码语言:javascript
复制
getSatHSVChannelAndBinarize[i_Image]             := Binarize@ColorSeparate[i, "HSB"][[2]]
removeSmallNoise[i_Image]                        := DeleteSmallComponents[i, 100]
fillSmallHoles[i_Image]                          := Closing[i, 1]
getMorphologicalComponentsAreas[i_Image]         := ComponentMeasurements[i, "Area"][[All, 2]]
roundAreaSizeToGrainCount[areaSize_, grainSize_] := Round[areaSize/grainSize]

同时处理所有图片:

代码语言:javascript
复制
counts = Plus @@@
  (roundAreaSizeToGrainCount[#, 2900] & /@
      (getMorphologicalComponentsAreas@
        fillSmallHoles@
         removeSmallNoise@
          getSatHSVChannelAndBinarize@#) & /@ im)

(* Output {3, 5, 12, 25, 49, 83, 118, 149, 152, 202} *)

得分是:

代码语言:javascript
复制
counts - {3, 5, 12, 25, 50, 83, 120, 150, 151, 200} // Abs // Total
(* 7 *)

在这里,您可以看到分数敏感性wrt所使用的晶粒大小:

票数 25
EN

Code Golf用户

发布于 2014-11-03 21:49:42

Python + OpenCV:

得分27

水平线扫描

想法:扫描图像,一次只扫描一行。对于每一行,计算遇到的米粒数(检查像素是变黑到白还是相反)。如果这条线的谷物数量增加(与前一行相比),那就意味着我们遇到了一个新的谷物。如果这个数字减少,就意味着我们通过了一颗谷物。在这种情况下,将+1添加到总结果中。

代码语言:javascript
复制
Number in red = rice grains encountered for that line
Number in gray = total amount of grains encountered (what we are looking for)

由于算法的工作方式,有一个干净的,b/w图像是很重要的。许多噪音会产生不好的结果。首先使用洪水(类似于Ell应答的溶液)清除主背景,然后应用阈值产生黑白结果。

它远非完美,但在简单性方面却产生了良好的效果。可能有很多方法来改进它(通过提供更好的b/w图像,在其他方向(例如:垂直、对角线)扫描平均值等.)

代码语言:javascript
复制
import cv2
import numpy
import sys

filename = sys.argv[1]
I = cv2.imread(filename, 0)
h,w = I.shape[:2]
diff = (3,3,3)
mask = numpy.zeros((h+2,w+2),numpy.uint8)
cv2.floodFill(I,mask,(0,0), (255,255,255),diff,diff)
T,I = cv2.threshold(I,180,255,cv2.THRESH_BINARY)
I = cv2.medianBlur(I, 7)

totalrice = 0
oldlinecount = 0
for y in range(0, h):
    oldc = 0
    linecount = 0
    start = 0   
    for x in range(0, w):
        c = I[y,x] < 128;
        if c == 1 and oldc == 0:
            start = x
        if c == 0 and oldc == 1 and (x - start) > 10:
            linecount += 1
        oldc = c
    if oldlinecount != linecount:
        if linecount < oldlinecount:
            totalrice += oldlinecount - linecount
        oldlinecount = linecount
print totalrice

每个图像的错误: 0,0,0,3,0,12,4,0,7,1

票数 31
EN

Code Golf用户

发布于 2014-11-02 09:03:50

Python + OpenCV: 84

这是第一次天真的尝试。它采用了人工调节参数的自适应阈值,关闭了一些随后发生腐蚀和稀释的洞,并从前景区域推导出晶粒数。

代码语言:javascript
复制
import cv2
import numpy as np

filename = raw_input()

I = cv2.imread(filename, 0)
I = cv2.medianBlur(I, 3)
bw = cv2.adaptiveThreshold(I, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 101, 1)

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (17, 17))
bw = cv2.dilate(cv2.erode(bw, kernel), kernel)

print np.round_(np.sum(bw == 0) / 3015.0)

在这里,您可以看到中间的二进制图像(黑色是前景):

每幅图像的误差分别为0、0、2、2、4、0、27、42、0和7粒。

票数 25
EN
页面原文内容由Code Golf提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codegolf.stackexchange.com/questions/40831

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档