Virtuelle Umkleidekabine in OpenCV

Hatten Sie so etwas, dass Ihnen etwas im Online-Shop gefallen hat, Sie es aber nicht kaufen möchten, ohne es anzuprobieren? In einigen GeschĂ€ften besteht natĂŒrlich die Möglichkeit, Kleidung nach der Bestellung vor der Zahlung anzuprobieren. Laut Statistik wĂ€chst der Anteil der Online-Bestellungen von Kleidung und Schuhen in Online-Shops jedes Jahr, aber auch der Anteil der Retouren steigt auf 50–70% - dies sind enorme Logistikkosten, die mit der Online-Umkleidekabine erheblich gesenkt werden können. Stellen Sie sich vor, Sie laden Ihr Foto hoch, wĂ€hlen Kleidung aus und es wird auf Ihr Bild ĂŒbertragen. Virtuelle Umkleidekabinen fĂŒr Schuhe gibt es bereits, sie funktionieren recht erfolgreich. Vor einiger Zeit haben wir uns fĂŒr dieses Thema interessiert, was ist mit Kleidung? Solche Werke existieren auch, aber viel weniger erfolgreiche, in vielen von ihnen ist neben dem Artikel nichts zu finden,Man kann nur von einem funktionierenden Beispiel trĂ€umen. Wir haben uns entschlossen, dies zu beheben und eines der Netzwerke in der OpenCV-Bibliothek zu unterstĂŒtzen. Was dabei herauskam, kann man sehenvirtual_try_on.py Beispiel.



Das Ergebnis ist nicht perfekt, wird aber in diesem Bereich als recht gut angesehen.


Wenn Sie wissen möchten, wie die virtuelle Umkleidekabine funktioniert und auf welche Schwierigkeiten wir bei der Integration des Modells in OpenCV gestoßen sind, sind Sie bei der Katze willkommen!


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.


, — , : , , . , .


Vorverarbeitung


.


GMM . , , L2−. . . , . c^ctL1−loss.


gmm


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


Io=M⊙c+(1−M)⊙Ir


⊙— .


Tom


Try-On — IoIt. . , , . L1−lossperceptual 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