غرفة القياس الافتراضية في OpenCV

هل لديك شيء أعجبك شيئًا في المتجر عبر الإنترنت ، لكنك لا تريد شرائه دون تجربته؟ بالطبع ، في بعض المتاجر هناك فرصة لتجربة الملابس بعد الطلب قبل السداد. ومع ذلك ، وفقًا للإحصاءات ، تزداد حصة الطلبات عبر الإنترنت في متاجر الملابس والأحذية عبر الإنترنت كل عام ، ولكن حصة العائدات تنمو أيضًا ، حيث تصل إلى 50-70٪ - وهي تكاليف لوجستية ضخمة يمكن تخفيضها بشكل كبير باستخدام غرفة القياس عبر الإنترنت. تخيل أنك تقوم بتحميل صورتك ، واختيار الملابس ويتم نقلها إلى صورتك. توجد بالفعل غرف تركيب افتراضية للأحذية ، وهي تعمل بنجاح كبير. منذ بعض الوقت ، كنا مهتمين بهذا الموضوع ، ماذا عن الملابس؟ توجد مثل هذه الأعمال أيضًا ، ولكنها أقل نجاحًا بكثير ؛ في العديد منها ، بالإضافة إلى المقالة ، لا يمكن العثور على شيء ،يمكن للمرء أن يحلم فقط مثال عملي. قررنا إصلاح هذا ودعم إحدى الشبكات الموجودة في مكتبة OpenCV. ما جاء من هذا يمكن رؤيته فينموذج virtual_try_on.py .



والنتيجة ليست مثالية ، ولكن في هذا المجال تعتبر جيدة جدًا.


إذا كنت تريد أن تعرف كيف تعمل غرفة القياس الافتراضية وما هي الصعوبات التي واجهناها عند دمج النموذج في OpenCV - مرحبًا بك في القطة!


2019 CP-VTON . CP-VTON , , (, ). 3D , 3D-. . github. CP-VTON , , .


.



CP-VTON : GMM (Geometric Matching Module) — TOM (Try-On Module) — .


GMM (I,c,ct), TOM — (I,c^,It), I— , c— , c^— GMM, It— ground truth ( c), ct— ground truth ( , It). , Itc. VITON, Ip. p, , , , (, , ). . , GMM (p,c)c^, ct. TOM (p,c^), IoIt.


p. , . OpenPose. . LIP_JPPNet. OpenCV () sample human_parsing.py.


, — , : , , . , .


المعالجة المسبقة


.


GMM . , , L2. . . , . c^ctL1loss.


غم


TOM . Unet. , . Unet , . , Unet . , . Upsample . (encoder) VGG-19. . Unet IrM. cIr, (1M)Io.


Io=Mc+(1M)Ir


— .


توم


Try-On — IoIt. . , , . L1lossperceptual loss. VGG , . VGG — , .


OpenCV


. json , OpenPose Caffe, LIP.


, , .


python3 virtual_try_on.py -i person_img.jpg -c cloth.jpg

OpenCV PIL. . LIP , . CP-VTON . , :


shape = (segm > 0).astype(np.float32)
head  = (segm == 1).astype(np.float32) + \
        (segm == 2).astype(np.float32) + \
        (segm == 4).astype(np.float32) + \
        (segm == 13).astype(np.float32)
cloth = (segm == 5).astype(np.float32) + \
        (segm == 6).astype(np.float32) + \
        (segm == 7).astype(np.float32)

, PIL , . human_colormap.mat. ? Matlab . , scipy . () .


– . 16 , .


mask = mask.resize((width // 16, height // 16), Image.BILINEAR)
mask = mask.resize((width, height), Image.BILINEAR)

. . , OpenCV. PIL resize cv.resize .



, PIL resize, — cv.resize.


, ? .


mask_pil mask_ocv


, PIL resize, — cv.resize.


, . ? , . , – . , bilinear resize bilinear, area. scale factor, 33 = 16 * 2 + 1, OpenCV – 3. , , . . . , . . :


PIL
class BilinearFilter(object):
    """
    PIL bilinear resize implementation
    image = image.resize((image_width // 16, image_height // 16), Image.BILINEAR)
    """
    def _precompute_coeffs(self, inSize, outSize):
        filterscale = max(1.0, inSize / outSize)
        ksize = int(np.ceil(filterscale)) * 2 + 1

        kk = np.zeros(shape=(outSize * ksize, ), dtype=np.float32)
        bounds = np.empty(shape=(outSize * 2, ), dtype=np.int32)

        centers = (np.arange(outSize) + 0.5) * filterscale + 0.5
        bounds[::2] = np.where(centers - filterscale < 0, 0, centers - filterscale)
        bounds[1::2] = np.where(centers + filterscale > inSize, inSize, centers + filterscale) - bounds[::2]
        xmins = bounds[::2] - centers + 1

        points = np.array([np.arange(row) + xmins[i] for i, row in enumerate(bounds[1::2])]) / filterscale
        for xx in range(0, outSize):
            point = points[xx]
            bilinear = np.where(point < 1.0, 1.0 - abs(point), 0.0)
            ww = np.sum(bilinear)
            kk[xx * ksize : xx * ksize + bilinear.size] = np.where(ww == 0.0, bilinear, bilinear / ww)
        return bounds, kk, ksize

    def _resample_horizontal(self, out, img, ksize, bounds, kk):
        for yy in range(0, out.shape[0]):
            for xx in range(0, out.shape[1]):
                xmin = bounds[xx * 2 + 0]
                xmax = bounds[xx * 2 + 1]
                k = kk[xx * ksize : xx * ksize + xmax]
                out[yy, xx] = np.round(np.sum(img[yy, xmin : xmin + xmax] * k))

    def _resample_vertical(self, out, img, ksize, bounds, kk):
        for yy in range(0, out.shape[0]):
            ymin = bounds[yy * 2 + 0]
            ymax = bounds[yy * 2 + 1]
            k = kk[yy * ksize: yy * ksize + ymax]
            out[yy] = np.round(np.sum(img[ymin : ymin + ymax, 0:out.shape[1]] * k[:, np.newaxis], axis=0))

    def imaging_resample(self, img, xsize, ysize):
        height, width, *args = img.shape
        bounds_horiz, kk_horiz, ksize_horiz = self._precompute_coeffs(width, xsize)
        bounds_vert, kk_vert, ksize_vert    = self._precompute_coeffs(height, ysize)

        out_hor = np.empty((img.shape[0], xsize), dtype=np.uint8)
        self._resample_horizontal(out_hor, img, ksize_horiz, bounds_horiz, kk_horiz)
        out = np.empty((ysize, xsize), dtype=np.uint8)
        self._resample_vertical(out, out_hor, ksize_vert, bounds_vert, kk_vert)
        return out


4 , , OpenCV. . , . , . 256 192, . sample . , - , .


P.S. 2020 OpenCV 20-. . !


All Articles