多云吗?


22

挑战

给定天空的图像,您必须以oktas输出云量。提供的图像将是图像文件(取决于您的类型),输出应为STDOUT。

奥克塔斯

在气象学中,okta是用于描述任何给定位置(如气象站)的云量的度量单位。根据云层覆盖了八分之几的天空来估算天空条件,范围从0 oktas(完全晴朗的天空)到8 oktas(完全多云)。

天空永远是中午左右的照片(所以,蓝天,不是红色/夜空)。

云的颜色将始终是遵循以下模式的颜色:

#ABCDEF

哪里AB >= C0CD >= C0EF >= C0

或者,在RGB中:

(A, B, C)

哪里A >= 192B >= 192C >= 192

以下是与Oktas相关的百分比覆盖率:

0%    - 0 oktas
12.5% - 1 okta
25%   - 2 oktas
37.5% - 3 oktas
50%   - 4 oktas
62.5% - 5 oktas
75%   - 6 oktas
87.5% - 7 oktas
100%  - 8 oktas

百分比是云图像的百分比。

如果图像的百分比云不是12.5的倍数,则应四舍五入到最接近的值。

输出量

输出应该只是okta编号(您不必说单位)。

例子

1 okta(18.030743615677714%云)

0 oktas(0.0%云)

3 1/8(42.66319444444445%云)

1 okta(12.000401814778645%云)

用于计算数字的Python代码

获奖

以字节为单位的最短代码获胜。


最后三张不是吗?
TheLethalCoder

@TheLethalCoder哎呀,编辑
Beta Decay

图像尺寸最大吗?
毛茸茸的

2
我添加了第四个测试用例,它需要四舍五入到12.5,因为使用整数下限的答案已经通过了前三个测试用例。
贾斯汀·马里纳

1
关于没有图像处理功能的语言(例如C ++),可以使用库吗?如果是这样,那么就字节数而言,它应该只计算编写的代码还是运行程序所需的DLL文件的大小?
HatsuPointerKun

Answers:


10

Python 2中114个 110 98字节

TheLethalCoder -4字节,Ruud
-12字节

import PIL.Image as P
i=P.open(input()).getdata()
print round(8.*sum(min(x)>191for x in i)/len(i))

在线尝试!


191代替吗?
TheLethalCoder

2
我本来建议x&y&z&192>191,但是更新的版本很短。
Arnauld

2
你能可能取代import PIL.Image as Pfrom PIL.Image import*和保存1个字节改变时i=P.openi=open?我不知道这是否会引起问题,因为open已经是一个已定义的函数,但是由于我无法安装该模块,因此无法测试。
阿诺德·帕尔默

1
是的,这似乎可行。节省1个字节。
Arfie

2
@Rod您的代码不必在所有平台上都可以运行-语言由解释器定义。如果它为您运行,那么它是有效的。
蒂姆(Tim)

10

MATL18 17字节

Yi191>3&A1eYm8*Yo

该示例使用提供的四张图像运行(抱歉预览质量;单击以获得完整分辨率):

在此处输入图片说明

或删除最后四个字符以查看结果而不四舍五入:

在此处输入图片说明

说明

Yi     % Implicitly input filename or URL. Read image. Gives an M×N×3 array
191>   % Does each entry exceed 191?
3&A    % True for 3rd-dim "lines" that only contain true. Gives an M×N matrix
1e     % Linearize (flatten) into a 1×L row vector, with L = M*N
Ym     % Mean of vector
8*     % Multiply by 8
Yo     % Round. Implicitly display

我不知道可以用esolangs做
ЕвгенийНовиков

6

Java(OpenJDK 8),204字节

i->{int x=0,y=0,t=0,w=i.getWidth(),h=i.getHeight();for(;x<w;)for(y=0;y<h;){java.awt.Color c=new java.awt.Color(i.getRGB(x++,y++));if(c.getRed()>191&&c.getBlue()>191&&c.getGreen()>191)t++;}return 8*t/w/h;}

在线尝试!我总是忘了TIO将STDERR输出到调试选项卡。如果在发生错误的情况下,它可能希望突出显示红色?


几件事:您的代码当前在无限循环中运行,因为您从不递增xy。您分配了y=0两次,因此可以删除第一个分配。该类Color必须是完全合格的(java.awt.Color),或者必须在字节数中包括导入。并且您的代码在第四个测试用例中失败(返回0而不是1)。
贾斯汀·马里纳

我知道已经有一段时间了,但是您可以通过移除内部for循环的括号,然后将&&to &,y=0to 更改为6字节来进行高尔夫,y在线尝试。
凯文·克鲁伊森

6

C#,150个 146字节

b=>{int t=0,c=0,w=0,h;for(;w<b.Width;++w)for(h=0;h<b.Height;++t){var p=b.GetPixel(w,h++);if(p.R>191&p.G>191&p.B>191)c++;}return(int)(c/(t+0d)*8);}

由于@Ian H,节省了4个字节。

完整/格式化版本:

using System.Drawing;

namespace System
{
    class P
    {
        static void Main()
        {
            Func<Bitmap, int> f = b =>
            {
                int t = 0, c = 0, w = 0, h;
                for (; w < b.Width; ++w)
                    for (h = 0; h < b.Height; ++t)
                    {
                        var p = b.GetPixel(w, h++);

                        if (p.R > 191 & p.G > 191 & p.B > 191)
                            c++;
                    }

                return (int)(c / (t + 0d) * 8);
            };

            string[] testCases =
            {
                @"Appearance_of_sky_for_weather_forecast,_Dhaka,_Bangladesh.JPG",
                @"spanish-sky.jpeg",
                @"why-is-sky-blue-1.jpg",
            };

            foreach (string testCase in testCases)
            {
                using (Bitmap bitmap = new Bitmap(testCase))
                {
                    Console.WriteLine(f(bitmap));
                }
            }

            Console.ReadLine();
        }
    }
}

for(h=0 h<b.Height;++t)我认为您错过了一个分号
Kritixi Lithos

2
您可以在末尾/0.125用替换*8以节省一些字节。
伊恩·H

@Cowsquack我删除了半冒号而不是空格!现在已修复..
TheLethalCoder

3

C#,313个字节

namespace System.Drawing.Imaging{b=>{unsafe{int t=0,c=0,y=0,x,w=b.Width,h=b.Height;var d=b.LockBits(new Rectangle(0,0,w,h),(ImageLockMode)1,(PixelFormat)137224);for(;y<h;++y){var r=(byte*)d.Scan0+y*d.Stride;for(x=0;x<w*3;++t)if(r[x++]>191&r[x++]>191&r[x++]>191)c++;}b.UnlockBits(d);return(int)(c/(t+0d)/0.125);}}}

显然比我的其他答案更长,但这是使用LockBitsunsafe代码直接访问内存中的图像的。因此,它非常快。我可能可以删除对的调用,UnlockBits但是在那里的更正确的选择。

完整/格式化版本:

namespace System.Drawing.Imaging
{
    class P
    {
        static void Main()
        {
            Func<Bitmap, int> f = b =>
            {
                unsafe
                {
                    int t = 0, c = 0, y = 0, x, w = b.Width, h = b.Height;

                    var d = b.LockBits(new Rectangle(0, 0, w, h), (ImageLockMode)1, (PixelFormat)137224);
                    for (; y < h; ++y)
                    {
                        var r = (byte*)d.Scan0 + y * d.Stride;

                        for (x = 0; x < w * 3; ++t)
                            if (r[x++] > 191 & r[x++] > 191 & r[x++] > 191)
                                c++;
                    }
                    b.UnlockBits(d);

                    return (int)(c / (t + 0d) / 0.125);
                }
            };

            string[] testCases =
            {
                @"Appearance_of_sky_for_weather_forecast,_Dhaka,_Bangladesh.JPG",
                @"spanish-sky.jpeg",
                @"why-is-sky-blue-1.jpg",
            };

            foreach (string testCase in testCases)
            {
                using (Bitmap bitmap = new Bitmap(testCase))
                {
                    Console.WriteLine(f(bitmap));
                }
            }

            Console.ReadLine();
        }
    }
}

3

PowerShell,200字节

$a=New-Object System.Drawing.Bitmap $args[0]
0..($a.Height-1)|%{$h=$_;0..($a.Width-1)|%{$i+=(("$($a.GetPixel($_,$h)|select R,G,B)"|iex)['R','G','B']-ge192).count-eq3}}
[int]($i/($a.Height*$a.Width)*8)

获取输入$args[0]作为完整图像文件路径,将New Bitmap对象构造为$a。这只是内部对象名称;它支持JPG,PNG等。

然后,我们依次遍历图像的.height和,依次.width触摸每个pixel。我们拉出R,G,B值,然后选择那些-greaterthanor eQUAL到192并确保count3(即,全部都是白色ISH)。该布尔结果将添加到我们的累加器中$i

然后,我们除以得到百分比,将其乘以8得到oktas的数量,然后[int]得到整数输出。(请注意,这将执行Banker的舍入-如果不允许这样做,将需要几个字节来更改舍入方法。)


2

dc,74位元组

???*sa?[1+]ss[r1+r]st[?191<s]su0ddsd[0luxluxlux3=t1+dla>r]dsrxr8*la2/+la/p

输入被视为P3 ppm文件,所有空格都作为换行符。输出到STDOUT。

在线尝试!


2

JavaScript,83 77字节

-6个字节的ETHproductions

f=i=>(z=a=b=0,i.map(e=>{z=e<192||z;(++b%4)||((z||(a+=64))&&(z=0))}),a/b+1>>1)

输入项

图片1

图片#2

图片#3

图片#4

演示版


1
非常好的解决方案。使用ES6箭头功能的一个方便技巧是将所有内容括在括号中,并用逗号(a=>(b,c,d))分隔,而不是执行a=>{b;c;return d}or a=>eval("b;c;d")。除非您有某种形式的循环,否则此方法有效,在这种情况下,最好使用该eval方法。
ETHproductions

2

C(POSIX),103个字节

假定输入为stdin上的BMP文件。

b,c,i,m=0xc0c0c0;main(){lseek(0,54,0);for(;read(0,&b,3);c+=(b&m)==m,i++);printf("%d",(i+16*c)/(2*i));}

2

x86机器代码,34个字节

51
31 D2
AD
F7 D0
25 C0 C0 C0 00
75 01
42
E2 F3
C1 E2 03
DB 04 24
52
DB 04 24
DE F1
DB 1C 24
58
5A
C3

这些代码字节定义了一个函数,该函数接受位图输入,并返回表示其oktas的整数值。与C中一样,数组(如位图)表示为指向第一个元素和大小/长度的指针。因此,此函数采用两个参数:位图中的像素总数(行×列)和指向位图本身的指针。

此代码使用基于寄存器的自定义调用约定,其中位图指针在ESI寄存器中传递,而位图大小在ECX寄存器中传递。通常,结果(oktas)返回EAX

如上所述,输入被当作位图。具体而言,使用32-bpp格式(低位字节序格式),但是忽略了alpha通道(最高位字节)。这简化了很多事情,使我们可以简单地遍历每个像素并检查其32位RGB颜色值。此处还使用了巧妙的优化。无需隔离每个颜色分量并检查其是否大于等于192,我们只需将整个32位值屏蔽为0xC0C0C0,然后测试结果是否大于等于0xC0C0C0。对于所有“云”颜色,这将评估为true;对于所有“天空”(非云)颜色,则评估为false。好吧,认为这很聪明!:-)当然可以节省大量字节。

因此,为了测试此代码,您将需要将输入图像转换为32 bpp位图。您不能为此使用Windows Paint,因为它最多支持每像素24位。但是,还有许多其他软件解决方案也可以做到这一点,例如Adobe Photoshop。我使用了这个免费工具,可以在Windows上将PNG转换为32-bpp BMP,这意味着您只需要从JPEG转换为PNG(Paint可以做到)。

我提出的其他假设非常合理:

  • 假定位图具有大于0的大小(,假定包含至少一个像素)。这是合理的,因为当天空为零时,我们要比气象学面临更大的问题。
  • DF假定方向标志()清楚,因此我们将使用LODSD指令正确地遍历位图。这与大多数x86调用约定所做的假设相同,因此似乎很公平。如果您不喜欢它,请在CLD指令计数中增加1个字节。
  • 假定x87 FPU的舍入模式设置为“舍入到最近”。这可以确保在将Oktas的数量从浮点临时转换为最终整数结果时得到正确的行为,如测试用例4所示。这种假设是合理的,因为这是FPU的默认状态,并且即使在C代码中也需要保持这种状态(其中截断是默认的舍入行为,这迫使希望符合标准的编译器生成无效的代码来更改舍入模式,进行转换,然后再将舍入模式更改回)。

非高尔夫装配助记符:

; int ComputeOktas(void*    bmpBits  /* ESI */,
;                  uint32_t bmpSize  /* ECX */);
   push  ecx                  ; save size on stack
   xor   edx, edx             ; EDX = 0 (cloudy pixel counter)

CheckPixels:
   lodsd                      ; EAX = DS:[ESI]; ESI += 4
   not   eax
   and   eax, 0x00C0C0C0
   jnz   NotCloudy
   inc   edx
NotCloudy:
   loop  CheckPixels          ; ECX -= 1; loop if ECX > 0

   shl    edx, 3              ; counter *= 8
   fild   DWORD PTR [esp]     ; load original size from stack
   push   edx
   fild   DWORD PTR [esp]     ; load counter from stack
   fdivrp st(1), st(0)        ; ST(0) = counter*8 / size
   fistp  DWORD PTR [esp]     ; convert to integer, rounding to nearest even
   pop    eax                 ; load result
   pop    edx
   ret

当然,您还没有完全解决问题,并且仍然想知道代码如何工作?:-)
很好,很简单。我们只一次遍历位图一个32位的值,以检查该像素RGB值是“多云”还是“不多云”。如果多云,我们增加预先调零的计数器。最后,我们计算:浑浊像素总像素  ×8
(相当于:浑浊像素总像素  ÷0.125)。

由于需要输入图像,我无法为此提供TIO链接。但是,我可以为您提供用于在Windows上进行测试的工具:

#include <stdio.h>
#include <assert.h>
#include <Windows.h>

int main()
{
   // Load bitmap as a DIB section under Windows, ensuring device-neutrality
   // and providing us direct access to its bits.
   HBITMAP hBitmap = (HBITMAP)LoadImage(NULL,
                                        TEXT("C:\\...\\test1.bmp"),
                                        IMAGE_BITMAP,
                                        0, 0,
                                        LR_LOADFROMFILE  | LR_CREATEDIBSECTION);
   assert(hBitmap != NULL);

   // Get the bitmap's bits and attributes.
   DIBSECTION dib;
   GetObject(hBitmap, sizeof(dib), &dib);
   assert(dib.dsBm.bmBitsPixel == 32);
   uint32_t cx = dib.dsBm.bmWidth;
   uint32_t cy = abs(dib.dsBm.bmHeight);
   uint32_t sz = cx * cy;
   assert(sz > 0);

   int oktas = ComputeOktas(sz, dib.dsBm.bmBits);

   printf("%d\n", oktas);

   return 0;
}

不过要小心!如上所定义,ComputeOktas使用C编译器将不遵守的自定义调用约定。您需要在汇编语言过程的顶部添加代码,以将堆栈中的值加载到预期的寄存器中,例如

mov  ecx, DWORD PTR [bmpSize]
mov  esi, DWORD PTR [bmpBits]

1

JavaScript(ES6),218个字节

(a,c=document.createElement`canvas`,w=c.width=a.width,h=c.height=a.height,x=c.getContext`2d`)=>x.drawImage(a,0,0)||x.getImageData(0,0,w,h).data.reduce((o,_,i,d)=>o+(i%4|d[i++]<192|d[i++]<192|d[i]<192?0:1),0)/w/h*8+.5|0

Image对象作为输入,可以从<image>元素创建它。

在CodePen上进行测试!

另类

如果输入可以作为RGBA值的平面数组,尺寸为:82个字节

(d,w,h)=>d.reduce((o,_,i)=>o+(i%4|d[i++]<192|d[i++]<192|d[i]<192?0:1),0)/w/h*8+.5|0

此输入格式与meta上的答案所建议的非常相似。


1

Mathematica 89字节

以下将图片二值化并确定云的比例,即白色像素。然后,它确定将结果乘以.125的次数。它返回该值的下限。

o@i_:=⌊8Tr@Flatten[ImageData@MorphologicalBinarize[i,.932],1]/Times@@ImageDimensions@i⌋
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.