과일에 그림을 그리는 이미지를 만드는 알고리즘

이 문서는 도완고 Advent Calendar 2018의 16 일째입니다. (늦었어요 😭)

오반입니다. 오늘은 옛날 만든, [사과]나【밤】,【수박】에, 탄 것 같은, 볶은 것 같은 가공을 하는 알고리즘을 소개하고 싶습니다.

과일에 그림을 그리는 것은



"합격 사과"를 아십니까? 수확 전 사과에 '합격' '수'라는 검은 씰을 붙이면 거기만 착색하지 않고 흰 노란색 글자가 쓰이는 농가의 솔루션입니다.
그것을 앱으로 실현한 '합격 사과'라는 앱을 공개했습니다. 1



이것은 선재 화상이므로, 농가의 솔루션이 알고 싶은 분은 「합격기원 사과」 2 로 화상 검색해 주세요.

사과만으로는 지루하지 않기 때문에 3 이번에는 밤의 알고리즘도 소개합니다. 이모는 개선하면 쓴다 4 .

쿠리 이미지


이모 이미지 (이번 소개는 없습니다)


그리고, 게다가 여름의 업데이트로 추가하려고 생각하고 있던, 수박의 알고리즘도 소개합니다.

수박 이미지


사과 알고리즘



이 응용 프로그램은 기본적으로 가공 전의 이미지와 가공 후의 이미지를 손가락으로 그린 ​​자국의 흑백 마스크로 겹칩니다.
가공 후의 화상은, 노란색이나 황록색을 포토쇼의 필터를 사용해 사과 부분에 겹쳐 작성했습니다.


-(void)penToBGImg:(UInt8*)penimg Before:(UInt8*)apple_before After:(UInt8*)apple_after
{
    UInt8* bgimg_tmp;
    UInt8* bgimg_white_tmp;
    for (int y = 0; y < pheight; y++) {
        for (int x = 0; x < pwidth; x++) {
    UInt8 pg = 0;
    if (pbitOffsetGreen != -1) {
        pg = *(penimg + y * pbytesPerRow + x * 4 + pbitOffsetGreen);
    }
    if(pg > 0.0f){

        bgimg_tmp = apple_before + y * bytesPerRow + x * 4;
        UInt8 r = 0;
        UInt8 g = 0;
        UInt8 b = 0;
        if (bitOffsetRed != -1) {
            r = *(bgimg_tmp + bitOffsetRed);
        }
        if (bitOffsetGreen != -1) {
            g = *(bgimg_tmp + bitOffsetGreen);
        }
        if (bitOffsetBlue != -1) {
            b = *(bgimg_tmp + bitOffsetBlue);
        }

        bgimg_white_tmp = apple_after + y * bytesPerRow + x * 4;
        UInt8 wr = 0;
        UInt8 wg = 0;
        UInt8 wb = 0;
        if (bitOffsetRed != -1) {
            wr = *(bgimg_white_tmp + bitOffsetRed);
        }
        if (bitOffsetGreen != -1) {
            wg = *(bgimg_white_tmp + bitOffsetGreen);
        }
        if (bitOffsetBlue != -1) {
            wb = *(bgimg_white_tmp + bitOffsetBlue);
        }

        // ビットマップに効果を与える
        float pa = pg / 255.0f;
        float ar = r * (1.0f - pa) + wr * pa;
        float ag = g * (1.0f - pa) + wg * pa;
        float ab = b * (1.0f - pa) + wb * pa;

        *(bgimg_tmp + bitOffsetRed) = ar;
        *(bgimg_tmp + bitOffsetGreen) = ag;
        *(bgimg_tmp + bitOffsetBlue) = ab;
    }
        }
    }
    bgimg_tmp = nil;
    bgimg_white_tmp = nil;
//    return apple_before;

}

사과의 경우 마스크 앞에 테두리를 3px 흐리게합니다.

흐림 없음 이미지


흐림 이미지

// りんごは ratio = 1 です
-(UInt8 *)blur:(UInt8 *)image myRatio:(int)ratio{
    for(int y=0; y<(int)pheight; y++){
        for(int x=0; x<(int)pwidth; x++){
            UInt8* bgimg_tmp;
            float r = 0;
            float g = 0;
            float b = 0;
//            float a = 0;
            int count = 0;
            for(int ay = -ratio; ay <= ratio; ay++){
                for(int ax = -ratio; ax <= ratio; ax++){
                    if(y + ay > 0 && y + ay < pheight
                       && x + ax > 0 && x + ax < pwidth){

                        bgimg_tmp = image + (y + ay) * pbytesPerRow + (x + ax) * 4;
                        if (pbitOffsetRed != -1) {
                            r += *(bgimg_tmp + pbitOffsetRed);
                        }
                        if (pbitOffsetGreen != -1) {
                            g += *(bgimg_tmp + pbitOffsetGreen);
                        }
                        if (pbitOffsetBlue != -1) {
                            b += *(bgimg_tmp + pbitOffsetBlue);
                        }

                        count++;
                    }
                }
            }
            r /= count;
            g /= count;
            b /= count;
//            a /= count;

            bgimg_tmp = image + y * pbytesPerRow + x * 4;
            *(bgimg_tmp + pbitOffsetRed) = r;
            *(bgimg_tmp + pbitOffsetGreen) = g;
            *(bgimg_tmp + pbitOffsetBlue) = b;
//            *(bgimg_tmp + pbitOffsetAlpha) = a;


        }
    }
    return image;
}

밤의 알고리즘



밤도 마찬가지로 가공 전과 가공 후의 이미지가 있고, 마스크하고 있습니다.
가공 후의 사진은 포토쇼에서 벗겨진 사진을 자르고, 회전시켜 붙여서 만들었습니다.
가공 후의 사진의, 무키 밤의 그림자는 브러쉬.


또, 마스크의 경계 부분(펜의 굵기의 경계선의, 반투명 부분)은 엷은 갈색으로 하는 처리를 하고 있습니다.
// 呼び出し元
        [self suicaMask:apple_before Pen:penimg Mask:@"mask_marron.png" R:137 G:3 B:0 A:1.0];

// スイカと共通のメソッド
-(void)suicaMask:(UInt8*)apple_before Pen:(UInt8*)pen_arr Mask:(NSString*)mask_str R:(float)red G:(float)green B:(float)blue A:(float)alpha
{
    UIImage* mask = [UIImage imageNamed:mask_str];
    UInt8* mask_arr = [self image2Array_dont_insert:mask];
    float r,g,b;

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            // スイカの形マスクから適当な一色を取得して、黒じゃなかったら画像処理
            UInt8 pr = 0;
            if (bitOffsetRed != -1) {
                pr = *(mask_arr + y * bytesPerRow + x * 4 + bitOffsetRed);
            }
            // 黒だったら処理をエスケープ(軽くしたい)
            if(pr > 0){
                // ペンマスクを取得
                UInt8 draw_px = 0;
                if (pbitOffsetRed != -1) {
                    draw_px = *(pen_arr + y * pbytesPerRow + x * 4 + pbitOffsetRed);
                }

                // ペンで描かれてるピクセルの場合
                if(draw_px > 0){
                    // すいか赤い部分を取得
                    UInt8* bgimg_tmp = apple_before + y * bytesPerRow + x * 4;
                    if (bitOffsetRed != -1) {
                        r = *(bgimg_tmp + bitOffsetRed);
                    }
                    if (bitOffsetGreen != -1) {
                        g = *(bgimg_tmp + bitOffsetGreen);
                    }
                    if (bitOffsetBlue != -1) {
                        b = *(bgimg_tmp + bitOffsetBlue);
                    }

                    // 透明度にあわせて白を代入
                    float pa = pr * alpha / 255.0f;
                    float ar = r * (1.0f - pa) + red * pa;
                    float ag = g * (1.0f - pa) + green * pa;
                    float ab = b * (1.0f - pa) + blue * pa;

                    if(ar > 255.0f)ar = 255.0f;
                    if(ar < 0.0f)ar = 0.0f;
                    if(ag > 255.0f)ag = 255.0f;
                    if(ag < 0.0f)ag = 0.0f;
                    if(ab > 255.0f)ab = 255.0f;
                    if(ab < 0.0f)ab = 0.0f;

                    *(bgimg_tmp + bitOffsetRed) = ar;
                    *(bgimg_tmp + bitOffsetGreen) = ag;
                    *(bgimg_tmp + bitOffsetBlue) = ab;

                }
            }
        }
    }
//    [mask release];
    mask = nil;
    mask_arr = nil;
}

수박 알고리즘



수박도 밤과 같습니다.
가공 후의 사진은, 반절반으로 한 수박의 화상을 포토쇼로 넣었습니다. (회전율이..)


가면.
아까의 메소드를, 흰색을 인수로 해 호출합니다.
(펜 테두리의 반투명 부분을, 수박은 흰색으로 그려져 있습니다.)
[self suicaMask:apple_before Pen:penimg R:255.0f G:255.0f B:255.0f];

결론



옛날의 기술이므로 「픽셀 가공이라든가 잔디」라고 삼키는 분도 계실지도 모릅니다. 그렇지만, 픽셀 가공은 아직 숨이 있다고 생각해... 하고 있습니다만...
이 응용 프로그램에서 사용하는 과일과 야채의 모든 이미지는 pixta에서 라이센스로 구입했습니다. 개인사용이라면 들키지 않습니다만, 인터넷에 올릴 때는 나와 같이 이미지를 라이센스 첨부로 구입하지 않으면 안 되기 때문에, 주의해 주세요. 이 앱으로 만든 이미지는 괜찮아 보입니다.



그것은 https를 지원하지 못하고 사라졌습니다 (부활 노력)

본 어플에서 '합격림수'라는 단어는 검색오염되어 버렸습니다.

(드롭)

(불평이므로)

좋은 웹페이지 즐겨찾기